File protobuf-4f02f056b5cea99052bfdfb6698afe47a3cf2964.patch of Package protobuf.26315

From 4f02f056b5cea99052bfdfb6698afe47a3cf2964 Mon Sep 17 00:00:00 2001
From: Rafi Kamal <rafikamal@google.com>
Date: Thu, 22 Aug 2019 16:14:22 -0700
Subject: [PATCH] Down integrate to GitHub

---
 java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java    |    9 
 java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java     |   10 
 java/core/src/main/java/com/google/protobuf/UnsafeUtil.java             |  318 ++++++++++
 java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java     |    4 
 java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java |   12 
 src/google/protobuf/compiler/java/java_file.cc                          |    3 
 src/google/protobuf/compiler/java/java_helpers.cc                       |    3 
 src/google/protobuf/compiler/java/java_helpers.h                        |    2 
 src/google/protobuf/compiler/java/java_message.cc                       |   10 
 src/google/protobuf/compiler/java/java_message_lite.cc                  |    7 
 src/google/protobuf/compiler/java/java_string_field.cc                  |    3 
 11 files changed, 366 insertions(+), 15 deletions(-)

--- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -146,6 +146,15 @@ public abstract class AbstractMessageLit
     Builder.addAll(values, list);
   }
 
+  /** Interface for an enum which signifies which field in a {@code oneof} was specified. */
+  protected interface InternalOneOfEnum {
+    /**
+     * Retrieves the field number of the field which was set in this {@code oneof}, or {@code 0} if
+     * none were.
+     */
+    int getNumber();
+  }
+
   /**
    * A partial implementation of the {@link Message.Builder} interface which implements as many
    * methods of that interface as possible in terms of other methods.
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -2365,6 +2365,11 @@ public abstract class GeneratedMessageV3
         }
         try {
           return new MethodHandleInvoker(accessor);
+        } catch (NoClassDefFoundError e) {
+          // Fall back to reflection if MethodHandleInvoker isn't available,
+          // allowing clients that don't want to use method handles to opt out
+          // by deleting the class.
+          return accessor;
         } catch (IllegalAccessException e) {
           throw new RuntimeException(e);
         }
@@ -2703,6 +2708,11 @@ public abstract class GeneratedMessageV3
         }
         try {
           return new MethodHandleInvoker(accessor);
+        } catch (NoClassDefFoundError e) {
+          // Fall back to reflection if MethodHandleInvoker isn't available,
+          // allowing clients that don't want to use method handles to opt out
+          // by deleting the class.
+          return accessor;
         } catch (IllegalAccessException e) {
           throw new RuntimeException(e);
         }
--- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
@@ -43,6 +43,9 @@ import java.util.logging.Logger;
 final class UnsafeUtil {
   private static final Logger logger = Logger.getLogger(UnsafeUtil.class.getName());
   private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+  private static final Class<?> MEMORY_CLASS = Android.getMemoryClass();
+  private static final boolean IS_ANDROID_64 = determineAndroidSupportByAddressSize(long.class);
+  private static final boolean IS_ANDROID_32 = determineAndroidSupportByAddressSize(int.class);
   private static final MemoryAccessor MEMORY_ACCESSOR = getMemoryAccessor();
   private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS =
       supportsUnsafeByteBufferOperations();
@@ -89,6 +92,9 @@ final class UnsafeUtil {
     return HAS_UNSAFE_BYTEBUFFER_OPERATIONS;
   }
 
+  static boolean isAndroid64() {
+    return IS_ANDROID_64;
+  }
 
   @SuppressWarnings("unchecked") // safe by method contract
   static <T> T allocateInstance(Class<T> clazz) {
@@ -314,6 +320,16 @@ final class UnsafeUtil {
     if (UNSAFE == null) {
       return null;
     }
+    if (Android.isOnAndroidDevice()) {
+      if (IS_ANDROID_64) {
+        return new Android64MemoryAccessor(UNSAFE);
+      } else if (IS_ANDROID_32) {
+        return new Android32MemoryAccessor(UNSAFE);
+      } else {
+        return null;
+      }
+    }
+
     return new JvmMemoryAccessor(UNSAFE);
   }
 
@@ -333,6 +349,9 @@ final class UnsafeUtil {
       clazz.getMethod("putLong", Object.class, long.class, long.class);
       clazz.getMethod("getObject", Object.class, long.class);
       clazz.getMethod("putObject", Object.class, long.class, Object.class);
+      if (Android.isOnAndroidDevice()) {
+        return true;
+      }
       clazz.getMethod("getByte", Object.class, long.class);
       clazz.getMethod("putByte", Object.class, long.class, byte.class);
       clazz.getMethod("getBoolean", Object.class, long.class);
@@ -365,6 +384,9 @@ final class UnsafeUtil {
         return false;
       }
 
+      if (Android.isOnAndroidDevice()) {
+        return true;
+      }
       clazz.getMethod("getByte", long.class);
       clazz.getMethod("putByte", long.class, byte.class);
       clazz.getMethod("getInt", long.class);
@@ -382,9 +404,36 @@ final class UnsafeUtil {
     return false;
   }
 
+  private static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) {
+    if (!Android.isOnAndroidDevice()) {
+      return false;
+    }
+    try {
+      Class<?> clazz = MEMORY_CLASS;
+      clazz.getMethod("peekLong", addressClass, boolean.class);
+      clazz.getMethod("pokeLong", addressClass, long.class, boolean.class);
+      clazz.getMethod("pokeInt", addressClass, int.class, boolean.class);
+      clazz.getMethod("peekInt", addressClass, boolean.class);
+      clazz.getMethod("pokeByte", addressClass, byte.class);
+      clazz.getMethod("peekByte", addressClass);
+      clazz.getMethod("pokeByteArray", addressClass, byte[].class, int.class, int.class);
+      clazz.getMethod("peekByteArray", addressClass, byte[].class, int.class, int.class);
+      return true;
+    } catch (Throwable t) {
+      return false;
+    }
+  }
 
   /** Finds the address field within a direct {@link Buffer}. */
   private static Field bufferAddressField() {
+    if (Android.isOnAndroidDevice()) {
+      // Old versions of Android had renamed the address field to 'effectiveDirectAddress', but
+      // recent versions of Android (>M?) use the OpenJDK implementation. Fall through in that case.
+      Field field = field(Buffer.class, "effectiveDirectAddress");
+      if (field != null) {
+        return field;
+      }
+    }
     Field field = field(Buffer.class, "address");
     return field != null && field.getType() == long.class ? field : null;
   }
@@ -656,4 +705,273 @@ final class UnsafeUtil {
     }
   }
 
+  private static final class Android64MemoryAccessor extends MemoryAccessor {
+
+    Android64MemoryAccessor(sun.misc.Unsafe unsafe) {
+      super(unsafe);
+    }
+
+    @Override
+    public byte getByte(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public byte getByte(Object target, long offset) {
+      if (IS_BIG_ENDIAN) {
+        return getByteBigEndian(target, offset);
+      } else {
+        return getByteLittleEndian(target, offset);
+      }
+    }
+
+    @Override
+    public void putByte(Object target, long offset, byte value) {
+      if (IS_BIG_ENDIAN) {
+        putByteBigEndian(target, offset, value);
+      } else {
+        putByteLittleEndian(target, offset, value);
+      }
+    }
+
+    @Override
+    public boolean getBoolean(Object target, long offset) {
+      if (IS_BIG_ENDIAN) {
+        return getBooleanBigEndian(target, offset);
+      } else {
+        return getBooleanLittleEndian(target, offset);
+      }
+    }
+
+    @Override
+    public void putBoolean(Object target, long offset, boolean value) {
+      if (IS_BIG_ENDIAN) {
+        putBooleanBigEndian(target, offset, value);
+      } else {
+        putBooleanLittleEndian(target, offset, value);
+      }
+    }
+
+    @Override
+    public float getFloat(Object target, long offset) {
+      return Float.intBitsToFloat(getInt(target, offset));
+    }
+
+    @Override
+    public void putFloat(Object target, long offset, float value) {
+      putInt(target, offset, Float.floatToIntBits(value));
+    }
+
+    @Override
+    public double getDouble(Object target, long offset) {
+      return Double.longBitsToDouble(getLong(target, offset));
+    }
+
+    @Override
+    public void putDouble(Object target, long offset, double value) {
+      putLong(target, offset, Double.doubleToLongBits(value));
+    }
+
+    @Override
+    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
+    }
+  }
+
+  private static final class Android32MemoryAccessor extends MemoryAccessor {
+
+    /** Mask used to convert a 64 bit memory address to a 32 bit address. */
+    private static final long SMALL_ADDRESS_MASK = 0x00000000FFFFFFFF;
+
+    /** Truncate a {@code long} address into a short {@code int} address. */
+    private static int smallAddress(long address) {
+      return (int) (SMALL_ADDRESS_MASK & address);
+    }
+
+    Android32MemoryAccessor(sun.misc.Unsafe unsafe) {
+      super(unsafe);
+    }
+
+    @Override
+    public byte getByte(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putByte(long address, byte value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getInt(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putInt(long address, int value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public long getLong(long address) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putLong(long address, long value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public byte getByte(Object target, long offset) {
+      if (IS_BIG_ENDIAN) {
+        return getByteBigEndian(target, offset);
+      } else {
+        return getByteLittleEndian(target, offset);
+      }
+    }
+
+    @Override
+    public void putByte(Object target, long offset, byte value) {
+      if (IS_BIG_ENDIAN) {
+        putByteBigEndian(target, offset, value);
+      } else {
+        putByteLittleEndian(target, offset, value);
+      }
+    }
+
+    @Override
+    public boolean getBoolean(Object target, long offset) {
+      if (IS_BIG_ENDIAN) {
+        return getBooleanBigEndian(target, offset);
+      } else {
+        return getBooleanLittleEndian(target, offset);
+      }
+    }
+
+    @Override
+    public void putBoolean(Object target, long offset, boolean value) {
+      if (IS_BIG_ENDIAN) {
+        putBooleanBigEndian(target, offset, value);
+      } else {
+        putBooleanLittleEndian(target, offset, value);
+      }
+    }
+
+    @Override
+    public float getFloat(Object target, long offset) {
+      return Float.intBitsToFloat(getInt(target, offset));
+    }
+
+    @Override
+    public void putFloat(Object target, long offset, float value) {
+      putInt(target, offset, Float.floatToIntBits(value));
+    }
+
+    @Override
+    public double getDouble(Object target, long offset) {
+      return Double.longBitsToDouble(getLong(target, offset));
+    }
+
+    @Override
+    public void putDouble(Object target, long offset, double value) {
+      putLong(target, offset, Double.doubleToLongBits(value));
+    }
+
+    @Override
+    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object getStaticObject(Field field) {
+      try {
+        return field.get(null);
+      } catch (IllegalAccessException e) {
+        return null;
+      }
+    }
+  }
+
+  private static byte getByteBigEndian(Object target, long offset) {
+    return (byte) ((getInt(target, offset & ~3) >>> ((~offset & 3) << 3)) & 0xFF);
+  }
+
+  private static byte getByteLittleEndian(Object target, long offset) {
+    return (byte) ((getInt(target, offset & ~3) >>> ((offset & 3) << 3)) & 0xFF);
+  }
+
+  private static void putByteBigEndian(Object target, long offset, byte value) {
+    int intValue = getInt(target, offset & ~3);
+    int shift = ((~(int) offset) & 3) << 3;
+    int output = (intValue & ~(0xFF << shift)) | ((0xFF & value) << shift);
+    putInt(target, offset & ~3, output);
+  }
+
+  private static void putByteLittleEndian(Object target, long offset, byte value) {
+    int intValue = getInt(target, offset & ~3);
+    int shift = (((int) offset) & 3) << 3;
+    int output = (intValue & ~(0xFF << shift)) | ((0xFF & value) << shift);
+    putInt(target, offset & ~3, output);
+  }
+
+  private static boolean getBooleanBigEndian(Object target, long offset) {
+    return getByteBigEndian(target, offset) != 0;
+  }
+
+  private static boolean getBooleanLittleEndian(Object target, long offset) {
+    return getByteLittleEndian(target, offset) != 0;
+  }
+
+  private static void putBooleanBigEndian(Object target, long offset, boolean value) {
+    putByteBigEndian(target, offset, (byte) (value ? 1 : 0));
+  }
+
+  private static void putBooleanLittleEndian(Object target, long offset, boolean value) {
+    putByteLittleEndian(target, offset, (byte) (value ? 1 : 0));
+  }
 }
--- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
@@ -345,8 +345,8 @@ public class FieldMaskUtil {
   }
 
   /**
-   * Merges fields specified by a FieldMask from one message to another with the
-   * specified merge options.
+   * Merges fields specified by a FieldMask from one message to another with the specified merge
+   * options. The destination will remain unchanged if an empty FieldMask is provided.
    */
   public static void merge(
       FieldMask mask, Message source, Message.Builder destination, MergeOptions options) {
--- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
@@ -182,11 +182,19 @@ public class FieldMaskTreeTest extends T
 
     FieldMaskUtil.MergeOptions options = new FieldMaskUtil.MergeOptions();
 
-    // Test merging each individual field.
+    // Test merging with an empty FieldMask.
     NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
+    builder.getPayloadBuilder().addRepeatedInt32(1000);
+    merge(new FieldMaskTree(), source, builder, options, useDynamicMessage);
+    NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
+    expected.getPayloadBuilder().addRepeatedInt32(1000);
+    assertEquals(expected.build(), builder.build());
+
+    // Test merging each individual field.
+    builder = NestedTestAllTypes.newBuilder();
     merge(new FieldMaskTree().addFieldPath("payload.optional_int32"),
         source, builder, options, useDynamicMessage);
-    NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
+    expected = NestedTestAllTypes.newBuilder();
     expected.getPayloadBuilder().setOptionalInt32(1234);
     assertEquals(expected.build(), builder.build());
 
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -238,7 +238,8 @@ bool FileGenerator::Validate(std::string
   }
 
   // Print a warning if optimize_for = LITE_RUNTIME is used.
-  if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME) {
+  if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME &&
+      !options_.enforce_lite) {
     GOOGLE_LOG(WARNING)
         << "The optimize_for = LITE_RUNTIME option is no longer supported by "
         << "protobuf Java code generator and is ignored--protoc will always "
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -32,13 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_helpers.h>
+
 #include <algorithm>
 #include <limits>
 #include <unordered_set>
 #include <vector>
 
 #include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -369,7 +369,7 @@ inline bool SupportUnknownEnumValue(cons
   return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
 }
 
-// Check whether a mesasge has repeated fields.
+// Check whether a message has repeated fields.
 bool HasRepeatedFields(const Descriptor* descriptor);
 
 inline bool IsMapEntry(const Descriptor* descriptor) {
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -417,9 +417,13 @@ void ImmutableMessageGenerator::Generate
                    "private int $oneof_name$Case_ = 0;\n"
                    "private java.lang.Object $oneof_name$_;\n");
     // OneofCase enum
-    printer->Print(vars,
-                   "public enum $oneof_capitalized_name$Case\n"
-                   "    implements com.google.protobuf.Internal.EnumLite {\n");
+    printer->Print(
+        vars,
+        "public enum $oneof_capitalized_name$Case\n"
+        // TODO(dweis): Remove EnumLite when we want to break compatibility with
+        // 3.x users
+        "    implements com.google.protobuf.Internal.EnumLite,\n"
+        "        com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
     printer->Indent();
     for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
       const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -237,9 +237,7 @@ void ImmutableMessageLiteGenerator::Gene
                    "private int $oneof_name$Case_ = 0;\n"
                    "private java.lang.Object $oneof_name$_;\n");
     // OneofCase enum
-    printer->Print(vars,
-                   "public enum $oneof_capitalized_name$Case\n"
-                   "    implements com.google.protobuf.Internal.EnumLite {\n");
+    printer->Print(vars, "public enum $oneof_capitalized_name$Case {\n");
     printer->Indent();
     for (int j = 0; j < oneof->field_count(); j++) {
       const FieldDescriptor* field = oneof->field(j);
@@ -277,7 +275,8 @@ void ImmutableMessageLiteGenerator::Gene
         "    default: return null;\n"
         "  }\n"
         "}\n"
-        "@java.lang.Override\n"
+        // TODO(b/135620659): Rename this to "getFieldNumber" or something to
+        // disambiguate it from actual proto enums.
         "public int getNumber() {\n"
         "  return this.value;\n"
         "}\n",
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -833,7 +833,8 @@ void RepeatedImmutableStringFieldGenerat
                  "  return $name$_.get(index);\n"
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
-  WriteFieldStringBytesAccessorDocComment(printer, descriptor_, LIST_ADDER);
+  WriteFieldStringBytesAccessorDocComment(printer, descriptor_,
+                                          LIST_INDEXED_GETTER);
   printer->Print(variables_,
                  "$deprecation$public com.google.protobuf.ByteString\n"
                  "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
openSUSE Build Service is sponsored by