diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py index dcde1d9420c9ab2db7a309322f914f123b045f1a..2ffaede1dac865af6063ce95f6db129cae5b4815 100644 --- a/python/google/protobuf/internal/decoder.py +++ b/python/google/protobuf/internal/decoder.py @@ -630,7 +630,13 @@ def GroupDecoder(field_number, is_repeated, is_packed, key, new_default): if value is None: value = field_dict.setdefault(key, new_default(message)) # Read sub-message. + current_depth += 1 + if current_depth > _recursion_limit: + raise _DecodeError( + 'Error parsing message: too many levels of nesting.' + ) pos = value.add()._InternalParse(buffer, pos, end) + current_depth -= 1 # Read end tag. new_pos = pos+end_tag_len if buffer[pos:new_pos] != end_tag_bytes or new_pos > end: @@ -647,7 +653,11 @@ def GroupDecoder(field_number, is_repeated, is_packed, key, new_default): if value is None: value = field_dict.setdefault(key, new_default(message)) # Read sub-message. + current_depth += 1 + if current_depth > _recursion_limit: + raise _DecodeError('Error parsing message: too many levels of nesting.') pos = value._InternalParse(buffer, pos, end) + current_depth -= 1 # Read end tag. new_pos = pos+end_tag_len if buffer[pos:new_pos] != end_tag_bytes or new_pos > end: @@ -677,10 +687,16 @@ def MessageDecoder(field_number, is_repeated, is_packed, key, new_default): if new_pos > end: raise _DecodeError('Truncated message.') # Read sub-message. + current_depth += 1 + if current_depth > _recursion_limit: + raise _DecodeError( + 'Error parsing message: too many levels of nesting.' + ) if value.add()._InternalParse(buffer, pos, new_pos) != new_pos: # The only reason _InternalParse would return early is if it # encountered an end-group tag. raise _DecodeError('Unexpected end-group tag.') + current_depth -= 1 # Predict that the next tag is another copy of the same repeated field. pos = new_pos + tag_len if buffer[new_pos:pos] != tag_bytes or new_pos == end: @@ -698,10 +714,14 @@ def MessageDecoder(field_number, is_repeated, is_packed, key, new_default): if new_pos > end: raise _DecodeError('Truncated message.') # Read sub-message. + current_depth += 1 + if current_depth > _recursion_limit: + raise _DecodeError('Error parsing message: too many levels of nesting.') if value._InternalParse(buffer, pos, new_pos) != new_pos: # The only reason _InternalParse would return early is if it encountered # an end-group tag. raise _DecodeError('Unexpected end-group tag.') + current_depth -= 1 return new_pos return DecodeField @@ -965,7 +985,11 @@ def _DecodeUnknownField(buffer, pos, wire_type): data = buffer[pos:pos+size].tobytes() pos += size elif wire_type == wire_format.WIRETYPE_START_GROUP: + current_depth += 1 + if current_depth >= _recursion_limit: + raise _DecodeError('Error parsing message: too many levels of nesting.') (data, pos) = _DecodeUnknownFieldSet(buffer, pos) + current_depth -= 1 elif wire_type == wire_format.WIRETYPE_END_GROUP: return (0, -1) else: @@ -995,6 +1019,14 @@ def _DecodeFixed32(buffer, pos): new_pos = pos + 4 return (struct.unpack('