Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lang/c/src/avro/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ avro_reader_memory_set_source(avro_reader_t reader, const char *buf, int64_t len
void
avro_writer_memory_set_dest(avro_writer_t writer, const char *buf, int64_t len);


/*
* Returns the number of bytes available to read from the reader.
* For memory readers, returns remaining bytes (len - read).
* For file readers, returns buffered bytes available.
* Returns -1 for unknown reader types.
*/
int64_t avro_max_read(avro_reader_t reader);

int avro_read(avro_reader_t reader, void *buf, int64_t len);
int avro_skip(avro_reader_t reader, int64_t len);
int avro_write(avro_writer_t writer, void *buf, int64_t len);
Expand Down
3 changes: 3 additions & 0 deletions lang/c/src/encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ typedef struct avro_encoding_t avro_encoding_t;
#define AVRO_SKIP(reader, len) \
{ int rval = avro_skip( reader, len); if (rval) return rval; }

#define AVRO_READ_OR_FREE(reader, buf, len, mem_size) \
{ int rval = avro_read( reader, buf, len ); if(rval) { if(buf) avro_free(buf, mem_size); buf = NULL; return rval; } }

extern const avro_encoding_t avro_binary_encoding; /* in
* encoding_binary
*/
Expand Down
25 changes: 23 additions & 2 deletions lang/c/src/encoding_binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,31 @@ static int64_t size_int(avro_writer_t writer, const int32_t i)
static int read_bytes(avro_reader_t reader, char **bytes, int64_t * len)
{
int rval;
int64_t max_available = -1;
check_prefix(rval, read_long(reader, len),
"Cannot read bytes length: ");
if (*len < 0) {
avro_set_error("Invalid bytes length: %" PRId64, *len);
return EINVAL;
}

max_available = avro_max_read(reader);
if (max_available >= 0 && str_len > max_available) {
avro_set_error("String length %" PRId64 " is greater than available buffer size %" PRId64,
str_len, max_available);
return ERANGE;
}


*bytes = (char *) avro_malloc(*len + 1);
if (!*bytes) {
avro_set_error("Cannot allocate buffer for bytes value");
return ENOMEM;
}
AVRO_READ(reader, *bytes, *len);

(*bytes)[*len] = '\0';
AVRO_READ_OR_FREE(reader, *bytes, *len, *len+1);

return 0;
}

Expand Down Expand Up @@ -180,21 +192,30 @@ size_bytes(avro_writer_t writer, const char *bytes, const int64_t len)
static int read_string(avro_reader_t reader, char **s, int64_t *len)
{
int64_t str_len = 0;
int64_t max_available = -1;
int rval;
check_prefix(rval, read_long(reader, &str_len),
"Cannot read string length: ");
if (str_len < 0) {
avro_set_error("Invalid string length: %" PRId64, str_len);
return EINVAL;
}

max_available = avro_max_read(reader);
if (max_available >= 0 && str_len > max_available) {
avro_set_error("String length %" PRId64 " is greater than available buffer size %" PRId64,
str_len, max_available);
return ERANGE;
}

*len = str_len + 1;
*s = (char *) avro_malloc(*len);
if (!*s) {
avro_set_error("Cannot allocate buffer for string value");
return ENOMEM;
}
(*s)[str_len] = '\0';
AVRO_READ(reader, *s, str_len);
AVRO_READ_OR_FREE(reader, *s, str_len, *len);
return 0;
}

Expand Down
14 changes: 14 additions & 0 deletions lang/c/src/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,20 @@ int avro_read(avro_reader_t reader, void *buf, int64_t len)
return EINVAL;
}


int64_t avro_max_read(avro_reader_t reader)
{
if (is_memory_io(reader)) {
struct _avro_reader_memory_t *mem_reader = avro_reader_to_memory(reader);
return mem_reader->len - mem_reader->read;
} else if (is_file_io(reader)) {
struct _avro_reader_file_t *file_reader = avro_reader_to_file(reader);
return bytes_available(file_reader);
Copy link
Member

Choose a reason for hiding this comment

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

This returns only the buffered bytes, not all remaining bytes as the memory io branch above

Copy link
Author

@kwenzh kwenzh Jan 28, 2026

Choose a reason for hiding this comment

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

sorry, I haven't found a way to get the remaining buffer length for file I/O. My goal is to check the maximum readable length before malloc to avoid memory leaks caused by the length exceeding the limit during avro_read_memory checks. Are there any other good solutions?

Copy link
Author

Choose a reason for hiding this comment

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

This returns only the buffered bytes, not all remaining bytes as the memory io branch above

maybe use (int64_t) sizeof(reader->buffer) , Am I understanding this correctly?

}
return -1;
}


static int avro_skip_memory(struct _avro_reader_memory_t *reader, int64_t len)
{
if (len > 0) {
Expand Down