From 342ae0ebc39221203cb44de4122c28d45d3a6eb8 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Thu, 29 Aug 2019 15:27:48 -0700 Subject: [PATCH] Fix issues for php map when parsing missing key/value (#6588) * For missing message value, map should create a default message instance in order to keep its invariable. * On 32-bit platform, int64 map key should be string --- php/src/Google/Protobuf/Internal/MapEntry.php | 14 ++++++++++ .../Google/Protobuf/Internal/MapFieldIter.php | 26 +++++++++++++------ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/php/src/Google/Protobuf/Internal/MapEntry.php b/php/src/Google/Protobuf/Internal/MapEntry.php index 9c32f1eac7..e89481f0a4 100644 --- a/php/src/Google/Protobuf/Internal/MapEntry.php +++ b/php/src/Google/Protobuf/Internal/MapEntry.php @@ -32,6 +32,7 @@ namespace Google\Protobuf\Internal; +use Google\Protobuf\Internal\GPBType; use Google\Protobuf\Internal\Message; class MapEntry extends Message @@ -39,6 +40,19 @@ class MapEntry extends Message public $key; public $value; + public function __construct($desc) { + parent::__construct($desc); + // For MapEntry, getValue should always return a valid value. Thus, we + // need to create a default instance value if the value type is + // message, in case no value is provided in data. + $value_field = $desc->getFieldByNumber(2); + if ($value_field->getType() == GPBType::MESSAGE) { + $klass = $value_field->getMessageType()->getClass(); + $value = new $klass; + $this->setValue($value); + } + } + public function setKey($key) { $this->key = $key; } diff --git a/php/src/Google/Protobuf/Internal/MapFieldIter.php b/php/src/Google/Protobuf/Internal/MapFieldIter.php index 88e6c8b255..4e18005ea8 100644 --- a/php/src/Google/Protobuf/Internal/MapFieldIter.php +++ b/php/src/Google/Protobuf/Internal/MapFieldIter.php @@ -91,14 +91,24 @@ class MapFieldIter implements \Iterator public function key() { $key = key($this->container); - if ($this->key_type === GPBType::BOOL) { - // PHP associative array stores bool as integer for key. - return boolval($key); - } elseif ($this->key_type === GPBType::STRING) { - // PHP associative array stores int string as int for key. - return strval($key); - } else { - return $key; + switch ($this->key_type) { + case GPBType::INT64: + case GPBType::UINT64: + case GPBType::FIXED64: + case GPBType::SFIXED64: + case GPBType::SINT64: + if (PHP_INT_SIZE === 8) { + return $key; + } + // Intentionally fall through + case GPBType::STRING: + // PHP associative array stores int string as int for key. + return strval($key); + case GPBType::BOOL: + // PHP associative array stores bool as integer for key. + return boolval($key); + default: + return $key; } }