-
Notifications
You must be signed in to change notification settings - Fork 0
3527: Avro-4193: [c] segfault cannot handle empty byte array #15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -156,7 +156,7 @@ static avro_datum_t avro_bytes_private(char *bytes, int64_t size, | |
| avro_datum_t avro_bytes(const char *bytes, int64_t size) | ||
| { | ||
| char *bytes_copy = (char *) avro_malloc(size); | ||
| if (!bytes_copy) { | ||
| if (!bytes_copy && size) { | ||
| avro_set_error("Cannot copy bytes content"); | ||
| return NULL; | ||
| } | ||
|
|
@@ -197,7 +197,7 @@ int avro_bytes_set(avro_datum_t datum, const char *bytes, const int64_t size) | |
| { | ||
| int rval; | ||
| char *bytes_copy = (char *) avro_malloc(size); | ||
| if (!bytes_copy) { | ||
| if (!bytes_copy && size) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As in 🤖 React with 👍 or 👎 to let us know if the comment was useful.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| avro_set_error("Cannot copy bytes content"); | ||
| return ENOMEM; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,18 +40,20 @@ test_allocator(void *ud, void *ptr, size_t osize, size_t nsize) | |
| AVRO_UNUSED(osize); | ||
|
|
||
| if (nsize == 0) { | ||
| size_t *size = ((size_t *) ptr) - 1; | ||
| if (osize != *size) { | ||
| fprintf(stderr, | ||
| "Error freeing %p:\n" | ||
| "Size passed to avro_free (%" PRIsz ") " | ||
| "doesn't match size passed to " | ||
| "avro_malloc (%" PRIsz ")\n", | ||
| ptr, osize, *size); | ||
| abort(); | ||
| //exit(EXIT_FAILURE); | ||
| if (ptr) { | ||
| size_t *size = ((size_t *) ptr) - 1; | ||
| if (osize != *size) { | ||
| fprintf(stderr, | ||
| "Error freeing %p:\n" | ||
| "Size passed to avro_free (%" PRIsz ") " | ||
| "doesn't match size passed to " | ||
| "avro_malloc (%" PRIsz ")\n", | ||
| ptr, osize, *size); | ||
| abort(); | ||
| //exit(EXIT_FAILURE); | ||
| } | ||
| free(size); | ||
| } | ||
| free(size); | ||
| return NULL; | ||
| } else { | ||
| size_t real_size = nsize + sizeof(size_t); | ||
|
|
@@ -214,6 +216,34 @@ static int test_bytes(void) | |
| return 0; | ||
| } | ||
|
|
||
| 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; | ||
| } | ||
|
Comment on lines
+219
to
+245
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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 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 🤖 Prompt for AI Agents
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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! 🐰 |
||
|
|
||
| static int test_int32(void) | ||
| { | ||
| int i; | ||
|
|
@@ -657,6 +687,7 @@ int main(void) | |
| { | ||
| "string", test_string}, { | ||
| "bytes", test_bytes}, { | ||
| "empty_bytes", test_empty_bytes}, { | ||
| "int", test_int32}, { | ||
| "long", test_int64}, { | ||
| "float", test_float}, { | ||
|
|
||
There was a problem hiding this comment.
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 subsequentmemcpymay be invoked with NULL pointers whensize == 0, which can be undefined behavior on some platforms. Please ensure the copy isn’t performed whensizeis zero (related issue also inavro_bytes_set).🤖 React with 👍 or 👎 to let us know if the comment was useful.
There was a problem hiding this comment.
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_copyis NULL andsizeis 0 theifcheck won't be true andmemcpy()will be called with a NULL argument as a destination. Thesizeshould be checked for 0 as a first step in this function and return early.