summaryrefslogtreecommitdiff
path: root/gdata/gdata-buffer.c
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2014-08-09 17:51:42 +0100
committerPhilip Withnall <philip@tecnocode.co.uk>2014-08-09 17:51:42 +0100
commit3809b38e6651ab6b533feea9cff0b95a0ccede95 (patch)
tree4b140edad0c8e637d7382a9bc14ca3f0ab6b8749 /gdata/gdata-buffer.c
parent3b0b4a0bacd38997980d3f0dd4aeaf82a44dc1a9 (diff)
downloadlibgdata-3809b38e6651ab6b533feea9cff0b95a0ccede95.tar.gz
core: Fix a data corruption bug in GDataBuffer
In some situations, the buffer was reading off the end of a chunk and into undefined memory. Spotted by asan. e.g. Take a GDataBuffer with two chunks: • Chunk 1, length 8192 • Chunk 2, length 699 and with head_read_offset = 8187 from a previous read. There are thus 704 bytes unread in the buffer. If a read of 8192 bytes is performed, 5 bytes should come from chunk 1 and the remaining 699 from chunk 2. length_remaining was being (correctly) set to 704, but then the while loop was not being entered, as 704 is not greater than or equal to 8192 (the length of chunk 1). The code was then falling into the G_LIKELY case below, and attempting to read 704 bytes from offset 8187 of chunk 1 — overreading by 699 bytes off the end of the chunk, and never getting the 699 bytes from chunk 2. This can be fixed by correctly taking the head_read_offset into account for the while condition.
Diffstat (limited to 'gdata/gdata-buffer.c')
-rw-r--r--gdata/gdata-buffer.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/gdata/gdata-buffer.c b/gdata/gdata-buffer.c
index 7b5c2fc2..e7b46991 100644
--- a/gdata/gdata-buffer.c
+++ b/gdata/gdata-buffer.c
@@ -268,7 +268,7 @@ gdata_buffer_pop_data (GDataBuffer *self, guint8 *data, gsize length_requested,
/* We can't assume we'll have enough data, since we may have reached EOF */
chunk = self->head;
- while (chunk != NULL && length_remaining >= chunk->length) {
+ while (chunk != NULL && self->head_read_offset + length_remaining >= chunk->length) {
GDataBufferChunk *next_chunk;
gsize chunk_length = chunk->length - self->head_read_offset;
@@ -292,6 +292,7 @@ gdata_buffer_pop_data (GDataBuffer *self, guint8 *data, gsize length_requested,
* been corrupted somewhere). */
if (G_LIKELY (length_remaining > 0)) {
g_assert (chunk != NULL);
+ g_assert_cmpuint (length_remaining, <=, chunk->length);
/* Copy the requested data to the output */
if (data != NULL) {