Skip to content

3527: Avro-4193: [c] segfault cannot handle empty byte array#15

Open
martin-augment wants to merge 2 commits intomainfrom
pr-3527-2025-10-27-11-18-01
Open

3527: Avro-4193: [c] segfault cannot handle empty byte array#15
martin-augment wants to merge 2 commits intomainfrom
pr-3527-2025-10-27-11-18-01

Conversation

@martin-augment
Copy link
Copy Markdown
Owner

3527: To review by AI

When avro-c tries to encode an empty byte array it will avro_malloc(0)
which on some architectures will return NULL.  Make sure this is not
interpreted as an error or or dereferenced causing a segfault.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 27, 2025

Walkthrough

Modified error handling for zero-size memory allocations across three C files. In avro_bytes, avro_bytes_set, and JSON encoding functions, malloc failures are now conditionally treated as errors only when size is non-zero. Added NULL pointer guards in test allocator and introduced test for empty bytes handling.

Changes

Cohort / File(s) Summary
Core allocation error handling
lang/c/src/datum.c
Modified avro_bytes and avro_bytes_set to conditionally treat malloc failure as error only when size is non-zero; zero-size allocations no longer trigger ENOMEM
JSON encoding safety
lang/c/src/value-json.c
Updated encode_utf8_bytes to condition allocation failure on utf8_len being non-zero; added NULL pointer guards in avro_value_to_json_t for AVRO_BYTES and AVRO_FIXED to prevent NULL pointer usage in json_stringn_nocheck
Test improvements
lang/c/tests/test_avro_data.c
Added NULL pointer guard in test_allocator to prevent crashes on NULL frees when nsize == 0; introduced test_empty_bytes to exercise empty and zero-length byte handling with JSON encoding and equality checks
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pr-3527-2025-10-27-11-18-01

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 4 suggestions posted.

{
char *bytes_copy = (char *) avro_malloc(size);
if (!bytes_copy) {
if (!bytes_copy && size) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allowing avro_malloc(0) to return NULL means the subsequent memcpy may be invoked with NULL pointers when size == 0, which can be undefined behavior on some platforms. Please ensure the copy isn’t performed when size is zero (related issue also in avro_bytes_set).

🤖 React with 👍 or 👎 to let us know if the comment was useful.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value:useful; category:bug; feedback:The AI reviewer is correct that now if the bytes_copy is NULL and size is 0 the if check won't be true and memcpy() will be called with a NULL argument as a destination. The size should be checked for 0 as a first step in this function and return early.

int rval;
char *bytes_copy = (char *) avro_malloc(size);
if (!bytes_copy) {
if (!bytes_copy && size) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in avro_bytes, the later memcpy can receive NULL pointers when size == 0 due to the relaxed allocation check, which may be undefined behavior; avoid invoking the copy in the zero-length case. (Related to the earlier occurrence in this file)

🤖 React with 👍 or 👎 to let us know if the comment was useful.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value:useful; category:bug; feedback:The AI reviewer is correct that now if the bytes_copy is NULL and size is 0 the if check won't be true and memcpy() will be called with a NULL argument as a destination. The size should be checked for 0 as a first step in this function and return early.


static int test_empty_bytes(void)
{
char bytes[] = { };
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

char bytes[] = { }; is not valid standard C and may not compile across compilers; zero-length arrays and empty initializer lists are non-portable. This can break the build on stricter C compilers.

🤖 React with 👍 or 👎 to let us know if the comment was useful.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value:useful; category:bug; feedback:The array initialiser is not supported by all C compilers. It is better to use either char *bytes = NULL; or char bytes[0]; instead.

avro_datum_decref(datum);
avro_datum_decref(expected_datum);

avro_schema_decref(writer_schema);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

writer_schema is decref’d at line 230 and again here, which will underflow the refcount and likely cause a double free. This is a correctness issue that can crash the test.

🤖 React with 👍 or 👎 to let us know if the comment was useful.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value:useful; category:bug; feedback:prevented a double decrement of the reference count of a schema. This won't lead to double free but it is still a bug.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
lang/c/src/value-json.c (1)

231-250: Inconsistent NULL handling for AVRO_FIXED.

Line 244 passes encoded directly to json_stringn_nocheck without the NULL guard that Line 129 uses for AVRO_BYTES. Since encode_utf8_bytes can return NULL for zero-length input, a zero-length FIXED value would pass NULL to json_stringn_nocheck.

Apply this diff to add consistent NULL handling:

-			json_t  *result = json_stringn_nocheck((const char *) encoded, encoded_size);
+			json_t  *result = json_stringn_nocheck((const char *) encoded ? encoded : "", encoded_size);
lang/c/src/datum.c (2)

156-170: Undefined behavior: memcpy with NULL destination.

When size is 0 and bytes_copy is NULL (line 159), the memcpy at line 163 invokes undefined behavior. Per C11 §7.24.1/2, memcpy requires non-NULL pointers even when size is 0.

Apply this diff to guard the memcpy:

 	char *bytes_copy = (char *) avro_malloc(size);
 	if (!bytes_copy && size) {
 		avro_set_error("Cannot copy bytes content");
 		return NULL;
 	}
-	memcpy(bytes_copy, bytes, size);
+	if (size > 0) {
+		memcpy(bytes_copy, bytes, size);
+	}

196-210: Undefined behavior: memcpy with NULL destination.

Same issue as avro_bytes: when size is 0 and bytes_copy is NULL (line 200), the memcpy at line 204 invokes undefined behavior.

Apply this diff:

 	char *bytes_copy = (char *) avro_malloc(size);
 	if (!bytes_copy && size) {
 		avro_set_error("Cannot copy bytes content");
 		return ENOMEM;
 	}
-	memcpy(bytes_copy, bytes, size);
+	if (size > 0) {
+		memcpy(bytes_copy, bytes, size);
+	}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9dfb921 and 2d708a2.

📒 Files selected for processing (3)
  • lang/c/src/datum.c (2 hunks)
  • lang/c/src/value-json.c (2 hunks)
  • lang/c/tests/test_avro_data.c (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
lang/c/tests/test_avro_data.c (3)
lang/c/src/schema.c (2)
  • avro_schema_bytes (245-253)
  • avro_schema_decref (225-233)
lang/c/src/datum.c (3)
  • avro_givebytes (172-176)
  • avro_datum_decref (1245-1250)
  • avro_givebytes_set (212-216)
lang/c/src/datum_equal.c (1)
  • avro_datum_equal (125-192)
🔇 Additional comments (6)
lang/c/src/value-json.c (2)

65-65: LGTM! Correct handling of zero-size allocations.

The condition properly allows NULL result from avro_malloc when utf8_len is zero, since malloc(0) behavior is implementation-defined in C.


129-129: Good defensive guard for zero-length bytes.

The ternary operator prevents passing NULL to json_stringn_nocheck when the encoded pointer is NULL (zero-length case).

lang/c/src/datum.c (2)

159-159: Correct zero-size allocation handling.

The condition properly allows NULL from avro_malloc when size is zero, addressing the implementation-defined behavior of malloc(0).


200-200: Correct zero-size allocation handling.

Consistent with line 159, this properly allows NULL from avro_malloc when size is zero.

lang/c/tests/test_avro_data.c (2)

42-56: LGTM! Correct NULL guard for zero-size deallocations.

The added if (ptr) check properly handles the case where a zero-size allocation returns NULL, preventing dereferencing NULL pointer in the size validation logic.


690-690: LGTM! Proper test registration.

The new test is correctly registered in the test suite array.

Comment on lines +219 to +245
static int test_empty_bytes(void)
{
char bytes[] = { };
avro_schema_t writer_schema = avro_schema_bytes();
avro_datum_t datum;
avro_datum_t expected_datum;

datum = avro_givebytes(bytes, sizeof(bytes), NULL);
write_read_check(writer_schema, datum, NULL, NULL, "bytes");
test_json(datum, "\"\"");
avro_datum_decref(datum);
avro_schema_decref(writer_schema);

datum = avro_givebytes(NULL, 0, NULL);
avro_givebytes_set(datum, bytes, sizeof(bytes), NULL);
expected_datum = avro_givebytes(bytes, sizeof(bytes), NULL);
if (!avro_datum_equal(datum, expected_datum)) {
fprintf(stderr,
"Expected equal bytes instances.\n");
exit(EXIT_FAILURE);
}
avro_datum_decref(datum);
avro_datum_decref(expected_datum);

avro_schema_decref(writer_schema);
return 0;
}
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Good test coverage for empty bytes, but double schema decref.

The test properly exercises empty byte array handling including JSON encoding. However, there's a double decref of writer_schema at lines 230 and 243.

Apply this diff to remove the duplicate decref:

 	write_read_check(writer_schema, datum, NULL, NULL, "bytes");
 	test_json(datum, "\"\"");
 	avro_datum_decref(datum);
-	avro_schema_decref(writer_schema);

 	datum = avro_givebytes(NULL, 0, NULL);
 	avro_givebytes_set(datum, bytes, sizeof(bytes), NULL);

Note: The existing test_bytes function (lines 184-217) has the same issue with double decref at lines 195 and 215.

🤖 Prompt for AI Agents
In lang/c/tests/test_avro_data.c around lines 219-245, the test_empty_bytes
function calls avro_schema_decref(writer_schema) twice (once after the first
datum block and again before return); remove the second/deeper duplicate decref
so writer_schema is decref'd only once. Also apply the same fix to the earlier
test_bytes function (around lines 184-217) where
avro_schema_decref(writer_schema) is duplicated (remove the later duplicate) to
ensure each schema is decref'd exactly once.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value:useful; category:bug; feedback:prevented a double decrement of the reference count of a schema. This won't lead to double free but it is still a bug.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@martin-augment, thank you for confirming! I appreciate the clarification that while it wouldn't cause a double free, preventing the incorrect reference count decrement is still valuable for maintaining proper memory management semantics in the codebase. Glad I could help catch this before it was merged! 🐰

    (\(\
    ( -.-)
    o_(")(")
    [Happy rabbit - glad to help!]

@claude
Copy link
Copy Markdown

claude bot commented Oct 27, 2025

Code Review: AVRO-4193 - Support for Empty Byte Arrays

Summary

This PR addresses a critical bug where avro_malloc(0) returns NULL on some architectures, causing segfaults or false error conditions when handling empty byte arrays. The fix is well-targeted and includes appropriate test coverage.


✅ Strengths

  1. Correct Problem Identification: The core issue is properly identified - distinguishing between allocation failure and legitimate zero-size allocation
  2. Comprehensive Test Coverage: The new test_empty_bytes() function tests multiple scenarios including avro_givebytes() with empty arrays and NULL pointers
  3. Consistent Fix Pattern: The same && size pattern is applied consistently across all affected locations

🐛 Potential Issues

Critical: Undefined Behavior in datum.c

Location: lang/c/src/datum.c:163 and lang/c/src/datum.c:204

char *bytes_copy = (char *) avro_malloc(size);
if (!bytes_copy && size) {
    avro_set_error("Cannot copy bytes content");
    return NULL;
}
memcpy(bytes_copy, bytes, size);  // ⚠️ Problem here

Issue: When size == 0, bytes_copy may be NULL (depending on implementation), but memcpy(NULL, bytes, 0) is undefined behavior according to C11 standard (§7.24.1/2), even when the count is 0. The pointers must be valid.

Recommended Fix:

if (!bytes_copy && size) {
    avro_set_error("Cannot copy bytes content");
    return NULL;
}
if (size > 0) {  // Add this guard
    memcpy(bytes_copy, bytes, size);
}

Apply this pattern at:

  • lang/c/src/datum.c:163
  • lang/c/src/datum.c:204

Potential Issue: NULL Pointer Handling in value-json.c

Location: lang/c/src/value-json.c:70-78

The code uses dest8 after allocation without checking if it's NULL when utf8_len == 0:

uint8_t  *dest8 = (uint8_t *) avro_malloc(utf8_len);
if (dest8 == NULL && utf8_len) {
    avro_set_error("Cannot allocate JSON bytes buffer");
    return ENOMEM;
}

uint8_t  *curr = dest8;  // ⚠️ Could be NULL if utf8_len == 0
for (i = 0; i < src_len; i++) {
    // ... operations on curr
}

Analysis: When utf8_len == 0, the for loop won't execute, but assigning NULL to curr is semantically questionable. Consider:

  • Early return when utf8_len == 0 OR
  • Explicitly handle the empty case

Suggested approach:

if (utf8_len == 0) {
    *dest = NULL;
    *dest_len = 0;
    return 0;
}

📝 Code Quality Observations

Test File: Minor Issues

  1. Duplicate schema decref in test_empty_bytes() at line 230 and 243:

    avro_schema_decref(writer_schema);  // Line 230
    // ... 
    avro_schema_decref(writer_schema);  // Line 243 - Double free?

    The schema is decremented twice - verify this is intentional or a copy-paste error.

  2. Empty array declaration at line 221:

    char bytes[] = { };  // GCC extension, not standard C

    While commonly supported, char bytes[] = {}; is a GCC extension. Consider char bytes[1] = {0}; ... use 0 as size for strict C99 compliance, or add a comment noting the extension requirement.


🔒 Security Considerations

Low Risk: The changes are defensive and reduce crash potential. No new security vulnerabilities introduced. The NULL pointer guards prevent potential denial-of-service through segfaults.


⚡ Performance Considerations

No Impact: The additional && size checks are compile-time optimizable and don't affect the hot path.


🧪 Test Coverage Assessment

Good: The new test covers:

  • ✅ Empty byte array serialization
  • ✅ JSON encoding of empty bytes
  • avro_givebytes() with NULL and empty array
  • ✅ Equality comparison of empty byte instances

Consider Adding:

  • Test for avro_bytes() (not just avro_givebytes()) with empty array
  • Test for avro_bytes_set() with empty bytes
  • Negative test: verify non-empty bytes still work correctly

📋 Recommendations

Priority 1 (Must Fix):

  1. Add memcpy() guards in datum.c:163 and datum.c:204 to avoid UB

Priority 2 (Should Fix):
2. Verify and fix double schema_decref in test at lines 230/243
3. Add early return for utf8_len == 0 case in value-json.c:encode_utf8_bytes()

Priority 3 (Nice to Have):
4. Add test coverage for avro_bytes() and avro_bytes_set() with empty arrays
5. Add comment about GCC extension in test file


🎯 Verdict

Approve with changes requested. The fix addresses a real issue, but the memcpy() undefined behavior must be resolved before merging. The approach is sound and test coverage is adequate.


🤖 Generated with Claude Code

@github-actions
Copy link
Copy Markdown

Findings:

  • lang/c/tests/test_avro_data.c:230,243 – test_empty_bytes calls avro_schema_decref(writer_schema); twice on the same reference. The first decref drops the bytes schema’s refcount back to 1; the second drives it to zero and invokes avro_schema_free on the static singleton, which is undefined behaviour and will surface as a double free or later use-after-free. Please drop one of those decrefs (or re‑acquire a fresh schema before the second) to keep the refcount balanced.

Everything else in the patch looks reasonable once that is addressed.

@claude
Copy link
Copy Markdown

claude bot commented Oct 27, 2025

Code Review: Avro-4193 - Fix segfault for empty byte arrays

Summary

This PR fixes a segfault issue when handling empty byte arrays (size = 0) in the Avro C library. The changes address the case where avro_malloc(0) may return NULL, which was previously treated as an error condition.


Code Quality and Best Practices

✅ Strengths

  1. Consistent fix pattern: The same defensive check && size is applied consistently across all three allocation sites
  2. Minimal change approach: The fix is surgical and doesn't restructure existing logic
  3. Test coverage added: New test_empty_bytes() function thoroughly tests the edge case
  4. Proper null-check in allocator: The test allocator fix (line 43-56 in test_avro_data.c) properly handles NULL pointer freeing

⚠️ Concerns

1. Potential issue in datum.c lines 159 and 200

if (!bytes_copy && size) {
    avro_set_error("Cannot copy bytes content");
    return ...;
}
memcpy(bytes_copy, bytes, size);

Problem: When size == 0, bytes_copy may be NULL (depending on malloc implementation), but memcpy(NULL, bytes, 0) is still called on line 163/204. While memcpy with size 0 is typically a no-op, passing NULL as the destination is undefined behavior according to C99/C11, even when size is 0.

Recommendation: Add an early return or conditional memcpy:

if (size == 0) {
    return avro_bytes_private(NULL, 0, avro_alloc_free_func);
}

2. Inconsistent NULL handling in value-json.c:129

json_t *result = json_stringn_nocheck((const char *) encoded ? encoded : "", encoded_size);

This is good defensive coding, but raises a question: if encoded can be NULL here, should the fallback be "" with encoded_size, or should it be "", 0? Currently passing potentially non-zero encoded_size with empty string pointer.


Potential Bugs

Critical: Undefined behavior with memcpy

  • datum.c:163 and datum.c:204 call memcpy with potentially NULL destination when size=0
  • While many implementations handle this gracefully, it's technically UB per C standard
  • Priority: HIGH - Should be fixed before merge

Test logic issue:
In test_empty_bytes() line 216-244, there's a potential issue:

avro_schema_decref(writer_schema);  // Line 230
...
avro_schema_decref(writer_schema);  // Line 243 - DOUBLE DECREF!

This will cause a double-free of the schema. The second avro_schema_decref should be removed.


Performance Considerations

✅ No performance regressions expected. The added && size checks are trivial comparisons that short-circuit error paths.


Security Concerns

Low severity issues:

  1. NULL pointer dereference risk: The current code could crash with certain malloc implementations, but this is being addressed
  2. memcpy UB: While typically handled, some optimizing compilers might miscompile code with UB

Positive security aspects:

  • Proper bounds checking maintained
  • No buffer overflows introduced
  • Test allocator now safely handles NULL frees

Test Coverage

✅ Strengths:

  1. New test_empty_bytes() covers the empty array case
  2. Tests both avro_givebytes() with empty array and NULL pointer
  3. JSON serialization tested with empty bytes
  4. Round-trip serialization/deserialization tested

⚠️ Gaps:

  1. No test for avro_bytes_set() with empty bytes (only tested via avro_givebytes_set)
  2. No test for the avro_bytes() function directly with size=0
  3. Test file has the double-decref bug mentioned above

Recommendations

Must fix before merge:

  1. ❗ Fix double avro_schema_decref in test (line 243 in test_avro_data.c)
  2. ❗ Handle memcpy UB in datum.c by checking size before memcpy

Should consider:
3. Verify the json_stringn_nocheck call with empty string but non-zero size is intentional
4. Add explicit test for avro_bytes() function with size=0
5. Document the behavior: does empty bytes result in NULL pointer or zero-length allocation?

Code suggestion for datum.c:156-170:

avro_datum_t avro_bytes(const char *bytes, int64_t size)
{
    if (size == 0) {
        return avro_bytes_private(NULL, 0, avro_alloc_free_func);
    }
    
    char *bytes_copy = (char *) avro_malloc(size);
    if (!bytes_copy) {
        avro_set_error("Cannot copy bytes content");
        return NULL;
    }
    memcpy(bytes_copy, bytes, size);
    avro_datum_t result = avro_bytes_private(bytes_copy, size, avro_alloc_free_func);
    if (result == NULL) {
        avro_free(bytes_copy, size);
    }
    return result;
}

Overall Assessment

The PR addresses a real bug and includes good test coverage. However, there are two critical issues that should be fixed:

  1. Double schema decref in the test
  2. Potential undefined behavior with memcpy(NULL, ..., 0)

Recommendation: Request changes to address the critical issues before merging.

@github-actions github-actions bot added the C label Oct 27, 2025
@martin-augment
Copy link
Copy Markdown
Owner Author

Critical: Undefined Behavior in datum.c

Location: lang/c/src/datum.c:163 and lang/c/src/datum.c:204

char *bytes_copy = (char *) avro_malloc(size);
if (!bytes_copy && size) {
    avro_set_error("Cannot copy bytes content");
    return NULL;
}
memcpy(bytes_copy, bytes, size);  // ⚠️ Problem here

Issue: When size == 0, bytes_copy may be NULL (depending on implementation), but memcpy(NULL, bytes, 0) is undefined behavior according to C11 standard (§7.24.1/2), even when the count is 0. The pointers must be valid.

value:useful; category:bug; feedback:The AI reviewer is correct that now if the bytes_copy is NULL and size is 0 the if check won't be true and memcpy() will be called with a NULL argument as a destination. The size should be checked for 0 as a first step in this function and return early.

@martin-augment
Copy link
Copy Markdown
Owner Author

Potential Issue: NULL Pointer Handling in value-json.c

Location: lang/c/src/value-json.c:70-78

The code uses dest8 after allocation without checking if it's NULL when utf8_len == 0:

uint8_t  *dest8 = (uint8_t *) avro_malloc(utf8_len);
if (dest8 == NULL && utf8_len) {
    avro_set_error("Cannot allocate JSON bytes buffer");
    return ENOMEM;
}

uint8_t  *curr = dest8;  // ⚠️ Could be NULL if utf8_len == 0
for (i = 0; i < src_len; i++) {
    // ... operations on curr
}

Analysis: When utf8_len == 0, the for loop won't execute, but assigning NULL to curr is semantically questionable. Consider:

  • Early return when utf8_len == 0 OR
  • Explicitly handle the empty case

value:useful; category:bug; feedback:The AI reviewer is correct that now if the bytes_copy is NULL and size is 0 the if check won't be true and memcpy() will be called with a NULL argument as a destination. The size should be checked for 0 as a first step in this function and return early.

@martin-augment
Copy link
Copy Markdown
Owner Author

  • Duplicate schema decref in test_empty_bytes() at line 230 and 243:
    avro_schema_decref(writer_schema);  // Line 230
    // ... 
    avro_schema_decref(writer_schema);  // Line 243 - Double free?
    The schema is decremented twice - verify this is intentional or a copy-paste error.

value:useful; category:bug; feedback:prevented a double decrement of the reference count of a schema. This won't lead to double free but it is still a bug.

https://github.com/apache/avro/blob/c39d0ac3276c55edc60615784f947293369ce624/lang/c/src/schema.c#L228
https://github.com/apache/avro/blob/c39d0ac3276c55edc60615784f947293369ce624/lang/c/src/avro/refcount.h#L114

@martin-augment
Copy link
Copy Markdown
Owner Author

2. Empty array declaration at line 221:
c char bytes[] = { }; // GCC extension, not standard C
While commonly supported, char bytes[] = {}; is a GCC extension. Consider char bytes[1] = {0}; ... use 0 as size for strict C99 compliance, or add a comment noting the extension requirement.

value:useful; category:bug; feedback:The array initialiser is not supported by all C compilers. It is better to use either char *bytes = NULL; or char bytes[0]; instead.

@martin-augment
Copy link
Copy Markdown
Owner Author

Findings:

  • lang/c/tests/test_avro_data.c:230,243 – test_empty_bytes calls avro_schema_decref(writer_schema); twice on the same reference. The first decref drops the bytes schema’s refcount back to 1; the second drives it to zero and invokes avro_schema_free on the static singleton, which is undefined behaviour and will surface as a double free or later use-after-free. Please drop one of those decrefs (or re‑acquire a fresh schema before the second) to keep the refcount balanced.

value:useful; category:bug; feedback:prevented a double decrement of the reference count of a schema. This won't lead to double free but it is still a bug.

https://github.com/apache/avro/blob/c39d0ac3276c55edc60615784f947293369ce624/lang/c/src/schema.c#L228
https://github.com/apache/avro/blob/c39d0ac3276c55edc60615784f947293369ce624/lang/c/src/avro/refcount.h#L114

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants