Skip to content

Commit

Permalink
Ignore unknown tags in message set items (google#856)
Browse files Browse the repository at this point in the history
  • Loading branch information
osa1 authored Jun 29, 2023
1 parent 2996e1d commit 0eb3796
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
28 changes: 28 additions & 0 deletions protobuf/lib/src/protobuf/coded_buffer_reader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,34 @@ class CodedBufferReader {
return _lastTag;
}

bool skipField(int tag) {
final tagType = getTagWireType(tag);

if (isAtEnd() || tagType == WIRETYPE_END_GROUP) {
return false;
}

switch (getTagWireType(tag)) {
case WIRETYPE_VARINT:
readInt64();
return true;
case WIRETYPE_FIXED64:
readFixed64();
return true;
case WIRETYPE_LENGTH_DELIMITED:
readBytes();
return true;
case WIRETYPE_FIXED32:
readFixed32();
return true;
case WIRETYPE_START_GROUP:
readUnknownFieldSetGroup(getTagFieldNumber(tag));
return true;
default:
throw InvalidProtocolBufferException.invalidWireType();
}
}

static int _decodeZigZag32(int value) {
if ((value & 0x1) == 1) {
return -(value >> 1) - 1;
Expand Down
5 changes: 4 additions & 1 deletion protobuf/lib/src/protobuf/message_set.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ abstract class $_MessageSet extends GeneratedMessage {
continue outer;
}
} else {
throw UnsupportedError('Invalid message set item (tag = $tagNumber)');
// Skip unknown tags.
if (!input.skipField(tag)) {
break outer; // End of group.
}
}
}
}
Expand Down
60 changes: 60 additions & 0 deletions protoc_plugin/test/message_set_test.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// Copyright (c) 2023, 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:fixnum/fixnum.dart';
import 'package:protobuf/protobuf.dart';
import 'package:test/test.dart';

import '../out/protos/google/protobuf/empty.pb.dart';
import '../out/protos/message_set.pb.dart';

void main() {
Expand Down Expand Up @@ -45,4 +51,58 @@ void main() {
expect(extensionValue.b, 'hi');
expect(msg.unknownFields.isEmpty, true);
});

test('Ignore extra item tags', () {
// Generate a message set encoding using unknown fields. Message set item
// will have extra tags.

final messageSetUnknownFields = UnknownFieldSet();

final itemField = UnknownFieldSetField();

final itemFieldGroup = UnknownFieldSet();

// Invalid field with tag 1.
itemFieldGroup.addField(
1, UnknownFieldSetField()..addLengthDelimited([1, 2, 3]));

// Extension field.
itemFieldGroup.addField(
3,
UnknownFieldSetField()
..addLengthDelimited((ExtensionMessage()
..a = 123456
..b = 'test')
.writeToBuffer()));

// Invalid field with tag 3.
itemFieldGroup.addField(
4, UnknownFieldSetField()..addVarint(Int64(123456)));

// Type id field.
itemFieldGroup.addField(
2, UnknownFieldSetField()..addVarint(Int64(1758024)));

itemField.addGroup(itemFieldGroup);

messageSetUnknownFields.addField(1, itemField);

final messageSetEncoded = CodedBufferWriter();
messageSetUnknownFields.writeToCodedBufferWriter(messageSetEncoded);

final encoded = (Empty()
..unknownFields.addField(
123,
UnknownFieldSetField()
..lengthDelimited.add(messageSetEncoded.toBuffer())))
.writeToBuffer();

final registry = ExtensionRegistry()..add(TestMessage.messageSetExtension);
final msg = TestMessage.fromBuffer(encoded, registry);
final extensionValue = msg.info
.getExtension(TestMessage.messageSetExtension) as ExtensionMessage;
expect(extensionValue.a, 123456);
expect(extensionValue.b, 'test');
expect(msg.unknownFields.isEmpty, true);
});
}

0 comments on commit 0eb3796

Please sign in to comment.