Skip to content

Commit 0c27f62

Browse files
committed
Fix potential out-of-bounds read access
Both 'key' and 'entry.prefix' may be bigger than table->n_entries.
1 parent 208b009 commit 0c27f62

File tree

1 file changed

+43
-44
lines changed

1 file changed

+43
-44
lines changed

src/image-gif.c

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static twin_gif_t *_twin_gif_open(const char *fname)
103103
read(fd, &fdsz, 1);
104104
/* Presence of GCT */
105105
if (!(fdsz & 0x80)) {
106-
fprintf(stderr, "no global color table_t\n");
106+
fprintf(stderr, "no global color table\n");
107107
goto fail;
108108
}
109109
/* Color Space's Depth */
@@ -159,44 +159,42 @@ static void discard_sub_blocks(twin_gif_t *gif)
159159
} while (size);
160160
}
161161

162-
static table_t *new_table_t(int key_size)
162+
static table_t *table_new(int key_size)
163163
{
164-
int key;
165164
int init_bulk = MAX(1 << (key_size + 1), 0x100);
166-
table_t *table_t = malloc(sizeof(*table_t) + sizeof(entry_t) * init_bulk);
167-
if (table_t) {
168-
table_t->bulk = init_bulk;
169-
table_t->n_entries = (1 << key_size) + 2;
170-
table_t->entries = (entry_t *) &table_t[1];
171-
for (key = 0; key < (1 << key_size); key++)
172-
table_t->entries[key] = (entry_t){1, 0xFFF, key};
165+
table_t *table = malloc(sizeof(*table) + sizeof(entry_t) * init_bulk);
166+
if (table) {
167+
table->bulk = init_bulk;
168+
table->n_entries = (1 << key_size) + 2;
169+
table->entries = (entry_t *) &table[1];
170+
for (int key = 0; key < (1 << key_size); key++)
171+
table->entries[key] = (entry_t){1, 0xFFF, key};
173172
}
174-
return table_t;
173+
return table;
175174
}
176175

177176
/* Add table_t entry_t. Return value:
178177
* 0 on success
179178
* +1 if key size must be incremented after this addition
180-
* -1 if could not realloc table_t
179+
* -1 if could not realloc table
181180
*/
182-
static int add_entry_t(table_t **table_tp,
183-
uint16_t length,
184-
uint16_t prefix,
185-
uint8_t suffix)
181+
static int entry_add(table_t **table_p,
182+
uint16_t length,
183+
uint16_t prefix,
184+
uint8_t suffix)
186185
{
187-
table_t *table_t = *table_tp;
188-
if (table_t->n_entries == table_t->bulk) {
189-
table_t->bulk *= 2;
190-
table_t = realloc(table_t,
191-
sizeof(*table_t) + sizeof(entry_t) * table_t->bulk);
192-
if (!table_t)
186+
table_t *table = *table_p;
187+
if (table->n_entries == table->bulk) {
188+
table->bulk *= 2;
189+
table = realloc(table, sizeof(*table) + sizeof(entry_t) * table->bulk);
190+
if (!table)
193191
return -1;
194-
table_t->entries = (entry_t *) &table_t[1];
195-
*table_tp = table_t;
192+
table->entries = (entry_t *) &table[1];
193+
*table_p = table;
196194
}
197-
table_t->entries[table_t->n_entries] = (entry_t){length, prefix, suffix};
198-
table_t->n_entries++;
199-
if ((table_t->n_entries & (table_t->n_entries - 1)) == 0)
195+
table->entries[table->n_entries] = (entry_t){length, prefix, suffix};
196+
table->n_entries++;
197+
if ((table->n_entries & (table->n_entries - 1)) == 0)
200198
return 1;
201199
return 0;
202200
}
@@ -266,8 +264,8 @@ static int read_image_data(twin_gif_t *gif, int interlace)
266264
int frm_off, frm_size, str_len = 0, i, p, x, y;
267265
uint16_t key, clear, stop;
268266
int ret;
269-
table_t *table_t;
270-
entry_t entry_t;
267+
table_t *table;
268+
entry_t entry = {0};
271269
off_t start, end;
272270

273271
read(gif->fd, &byte, 1);
@@ -281,7 +279,7 @@ static int read_image_data(twin_gif_t *gif, int interlace)
281279
lseek(gif->fd, start, SEEK_SET);
282280
clear = 1 << key_size;
283281
stop = clear + 1;
284-
table_t = new_table_t(key_size);
282+
table = table_new(key_size);
285283
key_size++;
286284
init_key_size = key_size;
287285
sub_len = shift = 0;
@@ -292,15 +290,15 @@ static int read_image_data(twin_gif_t *gif, int interlace)
292290
while (frm_off < frm_size) {
293291
if (key == clear) {
294292
key_size = init_key_size;
295-
table_t->n_entries = (1 << (key_size - 1)) + 2;
293+
table->n_entries = (1 << (key_size - 1)) + 2;
296294
is_table_full = false;
297295
} else if (!is_table_full) {
298-
ret = add_entry_t(&table_t, str_len + 1, key, entry_t.suffix);
296+
ret = entry_add(&table, str_len + 1, key, entry.suffix);
299297
if (ret == -1) {
300-
free(table_t);
298+
free(table);
301299
return -1;
302300
}
303-
if (table_t->n_entries == 0x1000) {
301+
if (table->n_entries == 0x1000) {
304302
ret = 0;
305303
is_table_full = true;
306304
}
@@ -310,28 +308,29 @@ static int read_image_data(twin_gif_t *gif, int interlace)
310308
continue;
311309
if (key == stop || key == 0x1000)
312310
break;
311+
if (key >= table->n_entries)
312+
break;
313313
if (ret == 1)
314314
key_size++;
315-
entry_t = table_t->entries[key];
316-
str_len = entry_t.length;
315+
entry = table->entries[key];
316+
str_len = entry.length;
317317
for (i = 0; i < str_len; i++) {
318-
p = frm_off + entry_t.length - 1;
318+
p = frm_off + entry.length - 1;
319319
x = p % gif->fw;
320320
y = p / gif->fw;
321321
if (interlace)
322322
y = interlaced_line_index((int) gif->fh, y);
323-
gif->frame[(gif->fy + y) * gif->width + gif->fx + x] =
324-
entry_t.suffix;
325-
if (entry_t.prefix == 0xFFF)
323+
gif->frame[(gif->fy + y) * gif->width + gif->fx + x] = entry.suffix;
324+
if (entry.prefix == 0xFFF || entry.prefix >= table->n_entries)
326325
break;
327326
else
328-
entry_t = table_t->entries[entry_t.prefix];
327+
entry = table->entries[entry.prefix];
329328
}
330329
frm_off += str_len;
331-
if (key < table_t->n_entries - 1 && !is_table_full)
332-
table_t->entries[table_t->n_entries - 1].suffix = entry_t.suffix;
330+
if (key < table->n_entries - 1 && !is_table_full)
331+
table->entries[table->n_entries - 1].suffix = entry.suffix;
333332
}
334-
free(table_t);
333+
free(table);
335334
if (key == stop)
336335
read(gif->fd, &sub_len, 1); /* Must be zero! */
337336
lseek(gif->fd, end, SEEK_SET);

0 commit comments

Comments
 (0)