Skip to content

Commit e8b6f74

Browse files
committed
AVRO-4275: Fix incomplete INT64_MIN overflow guard in block_count negation
Replace the flawed -(block_count + 1) + 1 idiom (which still overflows on the final + 1 when block_count == INT64_MIN) with an explicit INT64_MIN guard followed by simple negation, in both read_array_value() and read_map_value(). Also fix the block_size in the map test vector from 7 to 6 to match the actual byte count of the encoded entries. Assisted-by: GitHub Copilot:claude-opus-4.6
1 parent 271de63 commit e8b6f74

2 files changed

Lines changed: 10 additions & 14 deletions

File tree

lang/c/src/value-read.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,13 @@ read_array_value(avro_reader_t reader, avro_value_t *dest)
5353

5454
while (block_count != 0) {
5555
if (block_count < 0) {
56-
/* Safe negation: avoid undefined behavior when
57-
* block_count == INT64_MIN, since -INT64_MIN is not
58-
* representable in int64_t (CWE-190). Use the
59-
* -(x+1)+1 idiom to negate without overflow. */
60-
block_count = -(block_count + 1) + 1;
61-
if (block_count <= 0) {
56+
/* Reject INT64_MIN: its negation is not
57+
* representable in int64_t (CWE-190). */
58+
if (block_count == INT64_MIN) {
6259
avro_set_error("Invalid array block count");
6360
return EINVAL;
6461
}
62+
block_count = -block_count;
6563
check_prefix(rval, avro_binary_encoding.
6664
read_long(reader, &block_size),
6765
"Cannot read array block size: ");
@@ -97,15 +95,13 @@ read_map_value(avro_reader_t reader, avro_value_t *dest)
9795

9896
while (block_count != 0) {
9997
if (block_count < 0) {
100-
/* Safe negation: avoid undefined behavior when
101-
* block_count == INT64_MIN, since -INT64_MIN is not
102-
* representable in int64_t (CWE-190). Use the
103-
* -(x+1)+1 idiom to negate without overflow. */
104-
block_count = -(block_count + 1) + 1;
105-
if (block_count <= 0) {
98+
/* Reject INT64_MIN: its negation is not
99+
* representable in int64_t (CWE-190). */
100+
if (block_count == INT64_MIN) {
106101
avro_set_error("Invalid map block count");
107102
return EINVAL;
108103
}
104+
block_count = -block_count;
109105
check_prefix(rval, avro_binary_encoding.
110106
read_long(reader, &block_size),
111107
"Cannot read map block size: ");

lang/c/tests/test_avro_4275.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ static const char valid_neg_block_array[] = {
6363
*
6464
* Layout:
6565
* 03 = varint 3 = zigzag(-2) => block_count = -2
66-
* 0E = varint 14 = zigzag(7) => block_size = 7 bytes
66+
* 0C = varint 12 = zigzag(6) => block_size = 6 bytes
6767
* 02 61 14 = key "a" (len=1, 'a'), value int 10
6868
* 02 62 28 = key "b" (len=1, 'b'), value int 20
6969
* 00 = terminator
7070
*/
7171
static const char valid_neg_block_map[] = {
7272
'\x03', /* block_count = -2 */
73-
'\x0E', /* block_size = 7 */
73+
'\x0C', /* block_size = 6 */
7474
'\x02', '\x61', '\x14', /* key "a", value 10 */
7575
'\x02', '\x62', '\x28', /* key "b", value 20 */
7676
'\x00' /* terminator */

0 commit comments

Comments
 (0)