From 6fff091c49359ffd8550fc8228c79740b504a4fe Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Fri, 21 Apr 2017 15:00:00 -0700 Subject: Throw exception when parsing invalid data. (#3000) --- .../Protobuf/Internal/GPBDecodeException.php | 47 ++++++++++++++ php/src/Google/Protobuf/Internal/InputStream.php | 17 +++-- php/src/Google/Protobuf/Internal/Message.php | 73 +++++++++++++--------- 3 files changed, 96 insertions(+), 41 deletions(-) create mode 100644 php/src/Google/Protobuf/Internal/GPBDecodeException.php (limited to 'php/src/Google') diff --git a/php/src/Google/Protobuf/Internal/GPBDecodeException.php b/php/src/Google/Protobuf/Internal/GPBDecodeException.php new file mode 100644 index 00000000..402d542f --- /dev/null +++ b/php/src/Google/Protobuf/Internal/GPBDecodeException.php @@ -0,0 +1,47 @@ += 0 && $byte_limit <= PHP_INT_MAX - $current_position) { + if ($byte_limit >= 0 && + $byte_limit <= PHP_INT_MAX - $current_position && + $byte_limit <= $this->current_limit - $current_position) { $this->current_limit = $current_position + $byte_limit; + $this->recomputeBufferLimits(); } else { - // Negative or overflow. - $this->current_limit = PHP_INT_MAX; + throw new GPBDecodeException("Fail to push limit."); } - // We need to enforce all limits, not just the new one, so if the previous - // limit was before the new requested limit, we continue to enforce the - // previous limit. - $this->current_limit = min($this->current_limit, $old_limit); - - $this->recomputeBufferLimits(); return $old_limit; } @@ -370,7 +367,7 @@ class InputStream } public function incrementRecursionDepthAndPushLimit( - $byte_limit, &$old_limit, &$recursion_budget) + $byte_limit, &$old_limit, &$recursion_budget) { $old_limit = $this->pushLimit($byte_limit); $recursion_limit = --$this->recursion_limit; diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php index 887c86ca..cd15e0f0 100644 --- a/php/src/Google/Protobuf/Internal/Message.php +++ b/php/src/Google/Protobuf/Internal/Message.php @@ -224,48 +224,57 @@ class Message switch ($field->getType()) { case GPBType::DOUBLE: if (!GPBWire::readDouble($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside double field."); } break; case GPBType::FLOAT: if (!GPBWire::readFloat($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside float field."); } break; case GPBType::INT64: if (!GPBWire::readInt64($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside int64 field."); } break; case GPBType::UINT64: if (!GPBWire::readUint64($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside uint64 field."); } break; case GPBType::INT32: if (!GPBWire::readInt32($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside int32 field."); } break; case GPBType::FIXED64: if (!GPBWire::readFixed64($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside fixed64 field."); } break; case GPBType::FIXED32: if (!GPBWire::readFixed32($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside fixed32 field."); } break; case GPBType::BOOL: if (!GPBWire::readBool($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside bool field."); } break; case GPBType::STRING: // TODO(teboring): Add utf-8 check. if (!GPBWire::readString($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside string field."); } break; case GPBType::GROUP: @@ -280,43 +289,51 @@ class Message $value = new $klass; } if (!GPBWire::readMessage($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside message."); } break; case GPBType::BYTES: if (!GPBWire::readString($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside bytes field."); } break; case GPBType::UINT32: if (!GPBWire::readUint32($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside uint32 field."); } break; case GPBType::ENUM: // TODO(teboring): Check unknown enum value. if (!GPBWire::readInt32($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside enum field."); } break; case GPBType::SFIXED32: if (!GPBWire::readSfixed32($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside sfixed32 field."); } break; case GPBType::SFIXED64: if (!GPBWire::readSfixed64($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside sfixed64 field."); } break; case GPBType::SINT32: if (!GPBWire::readSint32($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside sint32 field."); } break; case GPBType::SINT64: if (!GPBWire::readSint64($input, $value)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside sint64 field."); } break; default: @@ -345,24 +362,21 @@ class Message } if ($value_format === GPBWire::NORMAL_FORMAT) { - if (!self::parseFieldFromStreamNoTag($input, $field, $value)) { - return false; - } + self::parseFieldFromStreamNoTag($input, $field, $value); } elseif ($value_format === GPBWire::PACKED_FORMAT) { $length = 0; if (!GPBWire::readInt32($input, $length)) { - return false; + throw new GPBDecodeException( + "Unexpected EOF inside packed length."); } $limit = $input->pushLimit($length); $getter = $field->getGetter(); while ($input->bytesUntilLimit() > 0) { - if (!self::parseFieldFromStreamNoTag($input, $field, $value)) { - return false; - } + self::parseFieldFromStreamNoTag($input, $field, $value); $this->$getter()[] = $value; } $input->popLimit($limit); - return true; + return; } else { return false; } @@ -377,8 +391,6 @@ class Message $setter = $field->getSetter(); $this->$setter($value); } - - return true; } /** @@ -567,7 +579,8 @@ class Message * specified message. * * @param string $data Binary protobuf data. - * @return bool Return true on success. + * @return null. + * @throws Exception Invalid data. */ public function mergeFromString($data) { @@ -595,9 +608,7 @@ class Message continue; } - if (!$this->parseFieldFromStream($tag, $input, $field)) { - return false; - } + $this->parseFieldFromStream($tag, $input, $field); } } -- cgit v1.2.3