-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Avro-4193: [c] segfault cannot handle empty byte array #3527
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) { | ||
|
Member
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. Same as above |
||
| avro_set_error("Cannot copy bytes content"); | ||
| return ENOMEM; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -62,7 +62,7 @@ encode_utf8_bytes(const void *src, size_t src_len, | |||||
|
|
||||||
| // Allocate a new buffer for the UTF-8 string and fill it in. | ||||||
| uint8_t *dest8 = (uint8_t *) avro_malloc(utf8_len); | ||||||
| if (dest8 == NULL) { | ||||||
| if (dest8 == NULL && utf8_len) { | ||||||
| avro_set_error("Cannot allocate JSON bytes buffer"); | ||||||
| return ENOMEM; | ||||||
| } | ||||||
|
|
@@ -126,7 +126,7 @@ avro_value_to_json_t(const avro_value_t *value) | |||||
| return NULL; | ||||||
| } | ||||||
|
|
||||||
| json_t *result = json_stringn_nocheck((const char *) encoded, encoded_size); | ||||||
| json_t *result = json_stringn_nocheck((const char *) encoded ? encoded : "", encoded_size); | ||||||
|
Member
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.
Suggested change
?
Member
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. There is a similar code for FIXED at https://github.com/steven-aerts/avro/blob/89fb9db03478b793be7188c5683c6560c2eff115/lang/c/src/value-json.c#L244 |
||||||
| avro_free(encoded, encoded_size); | ||||||
| if (result == NULL) { | ||||||
| avro_set_error("Cannot allocate JSON bytes"); | ||||||
|
|
||||||
| 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[] = { }; | ||||||
|
||||||
| char bytes[] = { }; | |
| char *bytes = NULL; |
Copilot
AI
Oct 27, 2025
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.
Double free: writer_schema is already decremented at line 230, so this second decrement at line 243 will cause a use-after-free error.
| avro_schema_decref(writer_schema); |
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.
What would happen now if
sizeis0?It looks to me that no matter what is the value of
bytes_copyit will never enter theifand it will callmemcpy(bytes_copy, bytes, 0)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.
IMO the there must be a check for
size == 0as a first step in this function that returns early and avoids any mallocs and memcpys.