Copilot commented on code in PR #3863:
URL: https://github.com/apache/avro/pull/3863#discussion_r3566990224
##########
lang/php/test/DatumIOTest.php:
##########
@@ -261,6 +262,277 @@ public function
test_invalid_bytes_logical_type_out_of_range(): void
$writer->write("10000", $encoder);
}
+ // A bytes/string value declares a length prefix; a malicious or truncated
+ // input can declare far more bytes than actually exist. On a reader that
+ // can report its size, that is rejected before allocating for it.
+ public function test_read_bytes_rejects_length_beyond_stream(): void
+ {
+ $io = new AvroStringIO();
+ (new AvroIOBinaryEncoder($io))->writeLong(100 * 1024 * 1024);
+ $io->seek(0);
+ $decoder = new AvroIOBinaryDecoder($io);
+
+ $this->expectException(AvroException::class);
+ $decoder->readBytes();
+ }
+
+ public function test_read_bytes_within_stream_still_reads(): void
+ {
+ $payload = str_repeat('x', 2 * 1024 * 1024);
+ $io = new AvroStringIO();
+ (new AvroIOBinaryEncoder($io))->writeBytes($payload);
+ $io->seek(0);
+ $decoder = new AvroIOBinaryDecoder($io);
+
+ $this->assertEquals($payload, $decoder->readBytes());
+ }
+
+ public function test_read_array_rejects_count_beyond_stream(): void
+ {
+ $io = new AvroStringIO();
+ (new AvroIOBinaryEncoder($io))->writeLong(1000000); // 1,000,000
longs, no data
+ $this->expectException(AvroException::class);
+ $this->decodeWith('{"type":"array","items":"long"}', $io);
+ }
+
+ public function test_read_map_rejects_count_beyond_stream(): void
+ {
+ $io = new AvroStringIO();
+ (new AvroIOBinaryEncoder($io))->writeLong(1000000);
+ $this->expectException(AvroException::class);
+ $this->decodeWith('{"type":"map","values":"long"}', $io);
+ }
+
+ public function test_read_array_of_null_not_falsely_rejected(): void
+ {
+ $count = 100000;
+ $io = new AvroStringIO();
+ $encoder = new AvroIOBinaryEncoder($io);
+ $encoder->writeLong($count); // one block of `count` nulls (zero bytes
each)
+ $encoder->writeLong(0); // end-of-array marker
+ $result = $this->decodeWith('{"type":"array","items":"null"}', $io);
+ $this->assertCount($count, $result);
+ }
+
+ public function test_read_array_within_stream_still_reads(): void
+ {
+ $schema = AvroSchema::parse('{"type":"array","items":"long"}');
+ $io = new AvroStringIO();
+ (new AvroIODatumWriter($schema))->write([1, 2, 3], new
AvroIOBinaryEncoder($io));
+ $this->assertEquals([1, 2, 3],
$this->decodeWith('{"type":"array","items":"long"}', $io));
+ }
+
+ public function test_array_of_null_exceeds_default_limit(): void
+ {
+ // The reported exploit: a ~6 byte payload declaring 200,000,000 nulls.
+ $this->expectException(AvroIOCollectionSizeException::class);
+ $this->decodeWith('{"type":"array","items":"null"}',
self::zeroByteBlock(200000000));
+ }
+
+ public function test_array_of_null_int64_min_block_count(): void
+ {
+ // PHP_INT_MIN as a block count cannot be negated (-PHP_INT_MIN
promotes
+ // to a float), so it must be rejected explicitly. It zig-zag encodes
as
+ // the 10-byte varint below, followed by a block byte-size (0).
+ $io = new AvroStringIO(
+ "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01\x00"
+ );
+ $this->expectException(AvroException::class);
+ $this->decodeWith('{"type":"array","items":"null"}', $io);
+ }
+
+ public function test_array_of_null_within_configured_limit_still_reads():
void
+ {
+ putenv('AVRO_MAX_COLLECTION_ITEMS=1000');
+
+ try {
+ $result = $this->decodeWith('{"type":"array","items":"null"}',
self::zeroByteBlock(1000));
+ $this->assertCount(1000, $result);
+ } finally {
+ putenv('AVRO_MAX_COLLECTION_ITEMS');
+ }
Review Comment:
These tests modify AVRO_MAX_COLLECTION_ITEMS but always unset it in the
finally block, which can break test isolation when the variable is already set
in the environment (e.g., by CI or a developer shell). Capture the previous
value before overriding and restore it in finally (apply the same pattern to
the other putenv blocks in this file).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]