Fix sharing coded buffer bytes when parsing `bytes` fields (#640)
Synced from internal repo
diff --git a/protobuf/lib/src/protobuf/coded_buffer.dart b/protobuf/lib/src/protobuf/coded_buffer.dart
index 45c3f4e..be316c4 100644
--- a/protobuf/lib/src/protobuf/coded_buffer.dart
+++ b/protobuf/lib/src/protobuf/coded_buffer.dart
@@ -53,7 +53,7 @@
fs._setFieldUnchecked(meta, fi, input.readBool());
break;
case PbFieldType._OPTIONAL_BYTES:
- fs._setFieldUnchecked(meta, fi, input.readBytes());
+ fs._setFieldUnchecked(meta, fi, Uint8List.fromList(input.readBytes()));
break;
case PbFieldType._OPTIONAL_STRING:
fs._setFieldUnchecked(meta, fi, input.readString());
@@ -126,7 +126,9 @@
_readPackable(meta, fs, input, wireType, fi, input.readBool);
break;
case PbFieldType._REPEATED_BYTES:
- fs._ensureRepeatedField(meta, fi).add(input.readBytes());
+ fs
+ ._ensureRepeatedField(meta, fi)
+ .add(Uint8List.fromList(input.readBytes()));
break;
case PbFieldType._REPEATED_STRING:
fs._ensureRepeatedField(meta, fi).add(input.readString());
diff --git a/protoc_plugin/Makefile b/protoc_plugin/Makefile
index aef823f..651302a 100644
--- a/protoc_plugin/Makefile
+++ b/protoc_plugin/Makefile
@@ -26,6 +26,7 @@
google/protobuf/unittest_well_known_types \
google/protobuf/unittest \
google/protobuf/wrappers \
+ bytes \
custom_option \
dart_name \
default_value_escape \
diff --git a/protoc_plugin/test/coded_buffer_test.dart b/protoc_plugin/test/coded_buffer_test.dart
new file mode 100644
index 0000000..e171f06
--- /dev/null
+++ b/protoc_plugin/test/coded_buffer_test.dart
@@ -0,0 +1,30 @@
+#!/usr/bin/env dart
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import '../out/protos/bytes.pb.dart';
+
+void main() {
+ test('Does not reuse input buffer for bytes fields', () {
+ var message = BytesEntity()..value = [1, 2, 3];
+ var bytes = message.writeToBuffer();
+ var deserialized1 = BytesEntity()..mergeFromBuffer(bytes);
+ var deserialized2 = BytesEntity()..mergeFromBuffer(bytes);
+ deserialized1.value[0] = 100;
+ expect(deserialized1.value[0], 100);
+ expect(deserialized2.value[0], 1);
+ });
+
+ test('Does not reuse input buffer for repeated bytes fields', () {
+ var message = BytesEntity()..values.add([1, 2, 3]);
+ var bytes = message.writeToBuffer();
+ var deserialized1 = BytesEntity()..mergeFromBuffer(bytes);
+ var deserialized2 = BytesEntity()..mergeFromBuffer(bytes);
+ deserialized1.values.first[0] = 100;
+ expect(deserialized1.values.first[0], 100);
+ expect(deserialized2.values.first[0], 1);
+ });
+}
diff --git a/protoc_plugin/test/protos/bytes.proto b/protoc_plugin/test/protos/bytes.proto
new file mode 100644
index 0000000..4ba43f3
--- /dev/null
+++ b/protoc_plugin/test/protos/bytes.proto
@@ -0,0 +1,6 @@
+syntax = "proto2";
+
+message BytesEntity {
+ optional bytes value = 1;
+ repeated bytes values = 2;
+}