Skip to content

libnsgif: Update to latest upstream. #2712

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

Merged
merged 1 commit into from
Mar 9, 2022
Merged
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
13 changes: 9 additions & 4 deletions libvips/foreign/libnsgif/README-ns.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,15 @@ Now you can load the GIF source data into the nsgif object with

This scans the source data and decodes information about each frame, however
it doesn't decode any of the bitmap data for the frames. The client may call
`nsgif_data_scan()` multiple times as source data is fetched. Once the
function has returned `NSGIF_OK` it has enough data to display at least one
frame. The early frames can be decoded before the later frames are scanned.
Frames have to be scanned before they can be decoded.
`nsgif_data_scan()` multiple times as source data is fetched. The early frames
can be decoded before the later frames are scanned. Frames have to be scanned
before they can be decoded.

This function will sometimes return an error. That is OK, and even expected.
It is fine to proceed to decoding any frames that are available after a scan.
Some errors indicate that there is a flaw in the source GIF data (not at all
uncommon, GIF is an ancient format that has had many broken encoders), or that
it has reached the end of the source data.

> **Note**: The client must not free the data until after calling
> `nsgif_destroy()`. You can move the data, e.g. if you realloc to a bigger
Expand Down
2 changes: 1 addition & 1 deletion libvips/foreign/libnsgif/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ but within the libvips build system.
Run `./update.sh` to update this copy of libnsgif from the upstream repo. It
will also patch libnsgif.c to prevent it modifying the input.

Last updated 3 Mar 2022.
Last updated 8 Mar 2022.

# To do

Expand Down
50 changes: 46 additions & 4 deletions libvips/foreign/libnsgif/gif.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,34 @@ static nsgif_error nsgif__parse_extension_graphic_control(
return NSGIF_OK;
}

/**
* Check an app ext identifier and authentication code for loop count extension.
*
* \param[in] data The data to decode.
* \param[in] len Byte length of data.
* \return true if extension is a loop count extension.
*/
static bool nsgif__app_ext_is_loop_count(
const uint8_t *data,
size_t len)
{
enum {
EXT_LOOP_COUNT_BLOCK_SIZE = 0x0b,
};

assert(len > 13);
(void)(len);

if (data[1] == EXT_LOOP_COUNT_BLOCK_SIZE) {
if (strncmp((const char *)data + 2, "NETSCAPE2.0", 11) == 0 ||
strncmp((const char *)data + 2, "ANIMEXTS1.0", 11) == 0) {
return true;
}
}

return false;
}

/**
* Parse the application extension
*
Expand All @@ -796,10 +824,24 @@ static nsgif_error nsgif__parse_extension_application(
return NSGIF_ERR_END_OF_DATA;
}

if ((data[1] == 0x0b) &&
(strncmp((const char *)data + 2, "NETSCAPE2.0", 11) == 0) &&
(data[13] == 0x03) && (data[14] == 0x01)) {
gif->info.loop_max = data[15] | (data[16] << 8);
if (nsgif__app_ext_is_loop_count(data, len)) {
enum {
EXT_LOOP_COUNT_SUB_BLOCK_SIZE = 0x03,
EXT_LOOP_COUNT_SUB_BLOCK_ID = 0x01,
};
if ((data[13] == EXT_LOOP_COUNT_SUB_BLOCK_SIZE) &&
(data[14] == EXT_LOOP_COUNT_SUB_BLOCK_ID)) {
gif->info.loop_max = data[15] | (data[16] << 8);

/* The value in the source data means repeat N times
* after the first implied play. A value of zero has
* the special meaning of loop forever. (The only way
* to play the animation once is not to have this
* extension at all. */
if (gif->info.loop_max > 0) {
gif->info.loop_max++;
}
}
}

return NSGIF_OK;
Expand Down
2 changes: 1 addition & 1 deletion libvips/foreign/libnsgif/nsgif.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ typedef struct nsgif_info {
uint32_t height;
/** number of frames decoded */
uint32_t frame_count;
/** number of times to loop animation */
/** number of times to play animation (zero means loop forever) */
int loop_max;
/** number of animation loops so far */
int loop_count;
Expand Down