aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Sufir <Sufir@users.noreply.github.com>2017-01-08 22:50:50 +0300
committerGravatar Paul Yang <TeBoring@users.noreply.github.com>2017-01-08 11:50:50 -0800
commit2bddffc993db05df57b6ebaea18f42c7b31753e9 (patch)
tree13a07943fc23b0ebf7682c246281989880d5e9e7
parent2c16f6979a03be84e359a09b92b28c87d57e5afc (diff)
PHP fix int64 decoding (#2516)
* fix int64 decoding * fix int64 decoding + tests
-rw-r--r--php/src/Google/Protobuf/Internal/InputStream.php75
-rw-r--r--php/tests/php_implementation_test.php30
2 files changed, 77 insertions, 28 deletions
diff --git a/php/src/Google/Protobuf/Internal/InputStream.php b/php/src/Google/Protobuf/Internal/InputStream.php
index 6d6c74e9..c5a76d5d 100644
--- a/php/src/Google/Protobuf/Internal/InputStream.php
+++ b/php/src/Google/Protobuf/Internal/InputStream.php
@@ -160,40 +160,59 @@ class InputStream
*/
public function readVarint64(&$var)
{
- $high = 0;
- $low = 0;
$count = 0;
- $b = 0;
-
- do {
- if ($this->current === $this->buffer_end) {
- return false;
- }
- if ($count === self::MAX_VARINT_BYTES) {
- return false;
- }
- $b = ord($this->buffer[$this->current]);
- $bits = 7 * $count;
- if ($bits >= 32) {
- $high |= (($b & 0x7F) << ($bits - 32));
- } else if ($bits > 25){
- $high_bits = $bits - 25;
- $low = ($low | (($b & 0x7F) << $bits)) & (int) 0xFFFFFFFF;
- $high = $b & ((0x1 << $high_bits) -1);
- } else {
- $low |= (($b & 0x7F) << $bits);
- }
-
- $this->advance(1);
- $count += 1;
- } while ($b & 0x80);
if (PHP_INT_SIZE == 4) {
+ $high = 0;
+ $low = 0;
+ $b = 0;
+
+ do {
+ if ($this->current === $this->buffer_end) {
+ return false;
+ }
+ if ($count === self::MAX_VARINT_BYTES) {
+ return false;
+ }
+ $b = ord($this->buffer[$this->current]);
+ $bits = 7 * $count;
+ if ($bits >= 32) {
+ $high |= (($b & 0x7F) << ($bits - 32));
+ } else if ($bits > 25){
+ $high_bits = $bits - 25;
+ $low = ($low | (($b & 0x7F) << $bits)) & (int) 0xFFFFFFFF;
+ $high = $b & ((0x1 << $high_bits) -1);
+ } else {
+ $low |= (($b & 0x7F) << $bits);
+ }
+
+ $this->advance(1);
+ $count += 1;
+ } while ($b & 0x80);
+
$var = combineInt32ToInt64($high, $low);
} else {
- $var = ($high & 0xFFFFFFFF) << 32 |
- ($low & 0xFFFFFFFF);
+ $result = 0;
+ $shift = 0;
+
+ do {
+ if ($this->current === $this->buffer_end) {
+ return false;
+ }
+ if ($count === self::MAX_VARINT_BYTES) {
+ return false;
+ }
+
+ $byte = ord($this->buffer[$this->current]);
+ $result |= ($byte & 0x7f) << $shift;
+ $shift += 7;
+ $this->advance(1);
+ $count += 1;
+ } while ($byte > 0x7f);
+
+ $var = $result;
}
+
return true;
}
diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php
index 4f626f1c..6b922a9b 100644
--- a/php/tests/php_implementation_test.php
+++ b/php/tests/php_implementation_test.php
@@ -366,6 +366,36 @@ class ImplementationTest extends TestBase
$this->assertSame(32768, $var);
}
$this->assertFalse($input->readVarint64($var));
+
+ // Read 64 testing
+ if (PHP_INT_SIZE > 4) {
+ $testVals = array(
+ '10' => '0a000000000000000000',
+ '100' => '64000000000000000000',
+ '800' => 'a0060000000000000000',
+ '6400' => '80320000000000000000',
+ '70400' => '80a60400000000000000',
+ '774400' => '80a22f00000000000000',
+ '9292800' => '8098b704000000000000',
+ '74342400' => '80c0b923000000000000',
+ '743424000' => '8080bfe2020000000000',
+ '8177664000' => '8080b5bb1e0000000000',
+ '65421312000' => '8080a8dbf30100000000',
+ '785055744000' => '8080e0c7ec1600000000',
+ '9420668928000' => '808080dd969202000000',
+ '103627358208000' => '808080fff9c717000000',
+ '1139900940288000' => '808080f5bd9783020000',
+ '13678811283456000' => '808080fce699a6180000',
+ '109430490267648000' => '808080e0b7ceb1c20100',
+ '984874412408832000' => '808080e0f5c1bed50d00',
+ );
+
+ foreach ($testVals as $original => $encoded) {
+ $input = new InputStream(hex2bin($encoded));
+ $this->assertTrue($input->readVarint64($var));
+ $this->assertSame($original, $var);
+ }
+ }
}
public function testReadVarint32()