From 039e59c0e60ea3fcab8eae775f59690847fa3459 Mon Sep 17 00:00:00 2001 From: dsavvinov Date: Thu, 11 Aug 2016 18:45:51 +0300 Subject: [PATCH] Protobuf: fixed a bug in serialization of negative generic integer types (int32, int64) --- .../src/main/kotlin/CodedInputStream.kt | 20 +++++++++---------- .../src/main/kotlin/CodedOutputStream.kt | 7 ++++++- proto/runtime/src/main/kotlin/WireFormat.kt | 3 +++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/proto/runtime/src/main/kotlin/CodedInputStream.kt b/proto/runtime/src/main/kotlin/CodedInputStream.kt index 5474b90fcc4..bbf2e58de41 100644 --- a/proto/runtime/src/main/kotlin/CodedInputStream.kt +++ b/proto/runtime/src/main/kotlin/CodedInputStream.kt @@ -150,22 +150,22 @@ class CodedInputStream(val buffer: ByteArray) { // reads varint not larger than 32-bit integer according to protobuf varint-encoding fun readInt32NoTag(): Int { var done: Boolean = false - var result: Int = 0 + var result: Long = 0 var step: Int = 0 while (!done) { val byte: Int = inputStream.read().toInt() result = result or ( - (byte and WireFormat.VARINT_INFO_BITS_MASK) - shl - (WireFormat.VARINT_INFO_BITS_COUNT * step) - ) + (byte and WireFormat.VARINT_INFO_BITS_MASK).toLong() + shl + (WireFormat.VARINT_INFO_BITS_COUNT * step) + ).toLong() step++ if ((byte and WireFormat.VARINT_UTIL_BIT_MASK) == 0) { done = true } } - return result + return result.toInt() } // reads varint not larger than 64-bit integer according to protobuf varint-encoding @@ -177,10 +177,10 @@ class CodedInputStream(val buffer: ByteArray) { val byte: Int = inputStream.read().toInt() result = result or ( - (byte and WireFormat.VARINT_INFO_BITS_MASK).toLong() - shl - (WireFormat.VARINT_INFO_BITS_COUNT * step) - ) + (byte and WireFormat.VARINT_INFO_BITS_MASK).toLong() + shl + (WireFormat.VARINT_INFO_BITS_COUNT * step) + ) step++ if ((byte and WireFormat.VARINT_UTIL_BIT_MASK) == 0 /* || byte == -1 ???? */) { done = true diff --git a/proto/runtime/src/main/kotlin/CodedOutputStream.kt b/proto/runtime/src/main/kotlin/CodedOutputStream.kt index a55d5a9f2c7..69b9efff821 100644 --- a/proto/runtime/src/main/kotlin/CodedOutputStream.kt +++ b/proto/runtime/src/main/kotlin/CodedOutputStream.kt @@ -99,7 +99,12 @@ class CodedOutputStream(val buffer: ByteArray) { * Then she/he can re-use low-level methods for operating with raw values, that are not annotated with Protobuf tags. */ - fun writeInt32NoTag(value: Int) { + fun writeInt32NoTag(value: Int) { + if (value < 0) { + writeInt64NoTag(value.toLong()) + return + } + var curValue: Int = value // we have at most 32 information bits. With overhead of 1 bit per 7 bits we need at most 5 bytes for encoding diff --git a/proto/runtime/src/main/kotlin/WireFormat.kt b/proto/runtime/src/main/kotlin/WireFormat.kt index 881ae1bd30b..ff1ba920f68 100644 --- a/proto/runtime/src/main/kotlin/WireFormat.kt +++ b/proto/runtime/src/main/kotlin/WireFormat.kt @@ -23,6 +23,9 @@ object WireFormat { } fun getVarint32Size(value: Int): Int { + if (value < 0) { + return getVarint64Size(value.toLong()) + } var curValue = value var size = 0 while (curValue != 0) {