This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/main by this push:
     new e45b60503 Fix long encoding (#3303)
e45b60503 is described below

commit e45b60503de3fd57c05aed5b70afb531ddca67b9
Author: Jonas Trevisan <[email protected]>
AuthorDate: Wed Feb 19 06:52:48 2025 -0300

    Fix long encoding (#3303)
---
 lang/php/lib/Datum/AvroIOBinaryDecoder.php |  2 +-
 lang/php/lib/Datum/AvroIOBinaryEncoder.php | 23 ++++++++++++++-----
 lang/php/test/DatumIOTest.php              | 36 ++++++++++++++++++++++++++----
 3 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/lang/php/lib/Datum/AvroIOBinaryDecoder.php 
b/lang/php/lib/Datum/AvroIOBinaryDecoder.php
index 870f56bd4..31a007f0a 100644
--- a/lang/php/lib/Datum/AvroIOBinaryDecoder.php
+++ b/lang/php/lib/Datum/AvroIOBinaryDecoder.php
@@ -124,7 +124,7 @@ class AvroIOBinaryDecoder
             $n |= (($b & 0x7f) << $shift);
             $shift += 7;
         }
-        return (($n >> 1) ^ -($n & 1));
+        return ($n >> 1) ^ (($n >> 63) << 63) ^ -($n & 1);
     }
 
     /**
diff --git a/lang/php/lib/Datum/AvroIOBinaryEncoder.php 
b/lang/php/lib/Datum/AvroIOBinaryEncoder.php
index 0a42b7480..d4c47248c 100644
--- a/lang/php/lib/Datum/AvroIOBinaryEncoder.php
+++ b/lang/php/lib/Datum/AvroIOBinaryEncoder.php
@@ -101,13 +101,24 @@ class AvroIOBinaryEncoder
     {
         $n = (int) $n;
         $n = ($n << 1) ^ ($n >> 63);
-        $str = '';
-        while (0 != ($n & ~0x7F)) {
-            $str .= chr(($n & 0x7F) | 0x80);
-            $n >>= 7;
+
+        if ($n >= 0 && $n < 0x80) {
+            return chr($n);
         }
-        $str .= chr($n);
-        return $str;
+
+        $buf = [];
+        if (($n & ~0x7F) != 0) {
+            $buf[] = ($n | 0x80) & 0xFF;
+            $n = ($n >> 7) ^ (($n >> 63) << 57); // unsigned shift right ($n 
>>> 7)
+
+            while ($n > 0x7F) {
+                $buf[] = ($n | 0x80) & 0xFF;
+                $n >>= 7; // $n is always positive here
+            }
+        }
+
+        $buf[] = $n;
+        return pack("C*", ...$buf);
     }
 
     /**
diff --git a/lang/php/test/DatumIOTest.php b/lang/php/test/DatumIOTest.php
index f8db66989..b2b879c1c 100644
--- a/lang/php/test/DatumIOTest.php
+++ b/lang/php/test/DatumIOTest.php
@@ -28,6 +28,12 @@ use Apache\Avro\IO\AvroStringIO;
 use Apache\Avro\Schema\AvroSchema;
 use PHPUnit\Framework\TestCase;
 
+/**
+ * @covers AvroIOBinaryDecoder
+ * @covers AvroIOBinaryEncoder
+ * @covers AvroIODatumReader
+ * @covers AvroIODatumWriter
+ */
 class DatumIOTest extends TestCase
 {
     /**
@@ -68,11 +74,33 @@ class DatumIOTest extends TestCase
             array('"int"', 1, "\002"),
             array('"int"', 2147483647, "\xFE\xFF\xFF\xFF\x0F"),
 
-            // array('"long"', (int) -9223372036854775808, "\001"),
+            array('"long"', (int) -9223372036854775808, 
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"),
+            array('"long"', -(1<<62), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F"),
+            array('"long"', -(1<<61), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x3F"),
+            array('"long"', -4294967295, "\xFD\xFF\xFF\xFF\x1F"),
+            array('"long"', -1<<24, "\xFF\xFF\xFF\x0F"),
+            array('"long"', -1<<16, "\xFF\xFF\x07"),
+            array('"long"', -255, "\xFD\x03"),
+            array('"long"', -128, "\xFF\x01"),
+            array('"long"', -127, "\xFD\x01"),
+            array('"long"', -10, "\x13"),
+            array('"long"', -3, "\005"),
+            array('"long"', -2, "\003"),
             array('"long"', -1, "\001"),
-            array('"long"', 0, "\000"),
-            array('"long"', 1, "\002"),
-            // array('"long"', 9223372036854775807, "\002")
+            array('"long"',  0, "\000"),
+            array('"long"',  1, "\002"),
+            array('"long"',  2, "\004"),
+            array('"long"',  3, "\006"),
+            array('"long"', 10, "\x14"),
+            array('"long"', 127, "\xFE\x01"),
+            array('"long"', 128, "\x80\x02"),
+            array('"long"', 255, "\xFE\x03"),
+            array('"long"', 1<<16, "\x80\x80\x08"),
+            array('"long"', 1<<24, "\x80\x80\x80\x10"),
+            array('"long"', 4294967295, "\xFE\xFF\xFF\xFF\x1F"),
+            array('"long"', 1<<61, "\x80\x80\x80\x80\x80\x80\x80\x80\x40"),
+            array('"long"', 1<<62, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x01"),
+            array('"long"', 9223372036854775807, 
"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01"),
 
             array('"float"', (float) -10.0, "\000\000 \301"),
             array('"float"', (float) -1.0, "\000\000\200\277"),

Reply via email to