Skip to content

Commit 0ec3a1e

Browse files
committed
libnsgif: Clip frames to LSD
This prevents a class of unexpectedly huge allocations in decoding.
1 parent e10880a commit 0ec3a1e

1 file changed

Lines changed: 32 additions & 6 deletions

File tree

libnsgif/libnsgif.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,23 @@ static gif_result gif_initialise_frame(gif_animation *gif)
372372
width = gif_data[5] | (gif_data[6] << 8);
373373
height = gif_data[7] | (gif_data[8] << 8);
374374

375+
/* Clip the extents to the LSD when we can. Reject when the
376+
* descriptor's origin is outside the screen, since clipping cannot
377+
* recover that. Without a guard, gif_initialise_sprite() below
378+
* is willing to grow the bitmap to (offset+extent) on each axis,
379+
* letting a 10-byte descriptor demand up to 16 GiB.
380+
*/
381+
if (offset_x + width > gif->width) {
382+
if (offset_x >= gif->width)
383+
return GIF_FRAME_DATA_ERROR;
384+
width = gif->width - offset_x;
385+
}
386+
if (offset_y + height > gif->height) {
387+
if (offset_y >= gif->height)
388+
return GIF_FRAME_DATA_ERROR;
389+
height = gif->height - offset_y;
390+
}
391+
375392
/* Set up the redraw characteristics. We have to check for extending
376393
* the area due to multi-image frames.
377394
*/
@@ -694,13 +711,22 @@ gif_internal_decode_frame(gif_animation *gif,
694711
width = gif_data[5] | (gif_data[6] << 8);
695712
height = gif_data[7] | (gif_data[8] << 8);
696713

697-
/* Boundary checking - shouldn't ever happen except unless the data has
698-
* been modified since initialisation.
714+
/* Clip extents to the logical screen — matches the bounds handling
715+
* in gif_initialise_frame().
699716
*/
700-
if ((offset_x + width > gif->width) ||
701-
(offset_y + height > gif->height)) {
702-
return_value = GIF_DATA_ERROR;
703-
goto gif_decode_frame_exit;
717+
if (offset_x + width > gif->width) {
718+
if (offset_x >= gif->width) {
719+
return_value = GIF_DATA_ERROR;
720+
goto gif_decode_frame_exit;
721+
}
722+
width = gif->width - offset_x;
723+
}
724+
if (offset_y + height > gif->height) {
725+
if (offset_y >= gif->height) {
726+
return_value = GIF_DATA_ERROR;
727+
goto gif_decode_frame_exit;
728+
}
729+
height = gif->height - offset_y;
704730
}
705731

706732
/* Decode the flags */

0 commit comments

Comments
 (0)