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

iemejia pushed a commit to branch avro-cpp-issue
in repository https://gitbox.apache.org/repos/asf/avro.git

commit e8b6f7459e2080eb4be7f69098cc6c7df810e0f6
Author: Ismaël Mejía <[email protected]>
AuthorDate: Sat Jul 11 10:17:39 2026 +0200

    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
---
 lang/c/src/value-read.c       | 20 ++++++++------------
 lang/c/tests/test_avro_4275.c |  4 ++--
 2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/lang/c/src/value-read.c b/lang/c/src/value-read.c
index 68ffc5795c..b7bc2f7e44 100644
--- a/lang/c/src/value-read.c
+++ b/lang/c/src/value-read.c
@@ -53,15 +53,13 @@ read_array_value(avro_reader_t reader, avro_value_t *dest)
 
        while (block_count != 0) {
                if (block_count < 0) {
-                       /* Safe negation: avoid undefined behavior when
-                        * block_count == INT64_MIN, since -INT64_MIN is not
-                        * representable in int64_t (CWE-190). Use the
-                        * -(x+1)+1 idiom to negate without overflow. */
-                       block_count = -(block_count + 1) + 1;
-                       if (block_count <= 0) {
+                       /* Reject INT64_MIN: its negation is not
+                        * representable in int64_t (CWE-190). */
+                       if (block_count == INT64_MIN) {
                                avro_set_error("Invalid array block count");
                                return EINVAL;
                        }
+                       block_count = -block_count;
                        check_prefix(rval, avro_binary_encoding.
                                     read_long(reader, &block_size),
                                     "Cannot read array block size: ");
@@ -97,15 +95,13 @@ read_map_value(avro_reader_t reader, avro_value_t *dest)
 
        while (block_count != 0) {
                if (block_count < 0) {
-                       /* Safe negation: avoid undefined behavior when
-                        * block_count == INT64_MIN, since -INT64_MIN is not
-                        * representable in int64_t (CWE-190). Use the
-                        * -(x+1)+1 idiom to negate without overflow. */
-                       block_count = -(block_count + 1) + 1;
-                       if (block_count <= 0) {
+                       /* Reject INT64_MIN: its negation is not
+                        * representable in int64_t (CWE-190). */
+                       if (block_count == INT64_MIN) {
                                avro_set_error("Invalid map block count");
                                return EINVAL;
                        }
+                       block_count = -block_count;
                        check_prefix(rval, avro_binary_encoding.
                                     read_long(reader, &block_size),
                                     "Cannot read map block size: ");
diff --git a/lang/c/tests/test_avro_4275.c b/lang/c/tests/test_avro_4275.c
index 5a15cabee6..ca93caf6c2 100644
--- a/lang/c/tests/test_avro_4275.c
+++ b/lang/c/tests/test_avro_4275.c
@@ -63,14 +63,14 @@ static const char valid_neg_block_array[] = {
  *
  * Layout:
  *   03        = varint 3 = zigzag(-2) => block_count = -2
- *   0E        = varint 14 = zigzag(7) => block_size = 7 bytes
+ *   0C        = varint 12 = zigzag(6) => block_size = 6 bytes
  *   02 61 14  = key "a" (len=1, 'a'), value int 10
  *   02 62 28  = key "b" (len=1, 'b'), value int 20
  *   00        = terminator
  */
 static const char valid_neg_block_map[] = {
     '\x03',                     /* block_count = -2 */
-    '\x0E',                     /* block_size = 7 */
+    '\x0C',                     /* block_size = 6 */
     '\x02', '\x61', '\x14',    /* key "a", value 10 */
     '\x02', '\x62', '\x28',    /* key "b", value 20 */
     '\x00'                      /* terminator */

Reply via email to