Skip to content

Commit 024498f

Browse files
thomasvlcopybara-github
authored andcommitted
[ObjC] Revise tag parsing to have a 5 byte limit.
There is now a conformane test that checks overlong varints within tags; revise the tag parsing to ensure it doesn't allow overlong values. PiperOrigin-RevId: 843754470
1 parent cbaf01a commit 024498f

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

conformance/failure_list_objc.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
# JSON input or output tests are skipped (in conformance_objc.m) as mobile
22
# platforms don't support JSON wire format to avoid code bloat.
3-
4-
Required.*.ProtobufInput.BadTag_OverlongVarint # Should have failed to parse, but didn't.

objectivec/GPBCodedInputStream.m

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,22 +206,33 @@ int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) {
206206
return 0;
207207
}
208208

209-
uint64_t rawTag = (uint64_t)ReadRawVarint64(state);
210-
state->lastTag = (int32_t)rawTag;
211-
// Following _upb_Decoder_DecodeLongTag logic, fail if this is >32bit value.
212-
if (rawTag > (uint64_t)UINT32_MAX) {
209+
// The conformance tests now limit things to ensue the varint for a tag fits in 5 bytes. The logic
210+
// for this parse is based on _upb_WireReader_ReadLongTag.
211+
uint64_t rawTag = 0;
212+
BOOL finishedParse = NO;
213+
for (int i = 0; i < 5; i++) {
214+
uint64_t byte = (uint64_t)ReadRawByte(state);
215+
rawTag |= (byte & 0x7F) << (i * 7);
216+
if ((byte & 0x80) == 0) {
217+
finishedParse = YES;
218+
break;
219+
}
220+
}
221+
if (!finishedParse || (rawTag > (uint64_t)UINT32_MAX)) {
213222
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Invalid tag");
214223
}
224+
uint32_t tag = (uint32_t)rawTag;
215225

216226
// Tags have to include a valid wireformat.
217-
if (!GPBWireFormatIsValidTag(state->lastTag)) {
227+
if (!GPBWireFormatIsValidTag(tag)) {
218228
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Invalid wireformat in tag.");
219229
}
220230
// Zero is not a valid field number.
221-
if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) {
231+
if (GPBWireFormatGetTagFieldNumber(tag) == 0) {
222232
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag,
223233
@"A zero field number on the wire is invalid.");
224234
}
235+
state->lastTag = (int32_t)tag;
225236
return state->lastTag;
226237
}
227238

0 commit comments

Comments
 (0)