In image_load_png(), in image.cxx, the rows variable is free()'d twice whenever there is an error during png_read_end():
static int /* O - 0 = success, -1 = fail */
image_load_png(image_t *img, /* I - Image pointer */
FILE *fp, /* I - File to read from */
int gray, /* I - 0 = color, 1 = grayscale */
int load_data)/* I - 1 = load image data, 0 = just info */
{
/* ... */
png_bytep *rows; /* PNG row pointers */
/* ... */
rows = NULL;
if (setjmp(png_jmpbuf(pp)))
{
progress_error(HD_ERROR_BAD_FORMAT, "PNG file contains errors!");
/* ... */
if (rows != NULL)
free(rows);
return (-1);
}
/* ... */
free(rows);
png_read_end(pp, info);
png_destroy_read_struct(&pp, &info, NULL);
return (0);
}
Before calling png_read_end(), the rows variable is freed but not set to NULL. If png_read_end() fails, the program will jump to png_jmpbuf, which will attempt to free rows again.
This bug is considered a security issue (CWE-415) under certain circumstances. An attacker is able to trigger this condition by linking a maliciously crafted PNG file in an HTML document.
Reproducer
git clone https://github.com/michaelrsweet/htmldoc && cd htmldoc
./configure && make -j$(nproc)
./htmldoc/htmldoc --webpage -f out.pdf ./poc.html
Result:
$ ./htmldoc/htmldoc --webpage -f out.pdf ./poc.html
...
libpng error: PNG unsigned integer out of range
ERR007: PNG file contains errors!
ERR011: Unable to load image file "./poc.png"!
free(): double free detected in tcache 2
In
image_load_png()
, in image.cxx, therows
variable isfree()
'd twice whenever there is an error duringpng_read_end()
:Before calling
png_read_end()
, therows
variable is freed but not set to NULL. Ifpng_read_end()
fails, the program will jump topng_jmpbuf
, which will attempt to freerows
again.This bug is considered a security issue (CWE-415) under certain circumstances. An attacker is able to trigger this condition by linking a maliciously crafted PNG file in an HTML document.
Reproducer
git clone https://github.com/michaelrsweet/htmldoc && cd htmldoc
./configure && make -j$(nproc)
./htmldoc/htmldoc --webpage -f out.pdf ./poc.html
Result:
htmldoc_poc1.zip