libpng
libpng copied to clipboard
Division by zero error in png_image_write_main if Image width is zero
In png_image_write_main, the function checks overflow by :
png_uint_32 png_row_stride = image->width * channels;
...
if (image->height > 0xffffffffU/png_row_stride)
...
if the width is zero in image structure, the png_row_stride will be zero, and it brings a division by zero error.
we can reproduce the error by calling API functions png_image_write_to_stdio, png_image_write_to_memory and png_image_write_to_file.
For example.
#include "png.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef unsigned int usize;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef int isize;
typedef float f32;
typedef double f64;
int main() {
png_image v0_tmp[] = {{ NULL, 1, 7, 1, 25, 8, 9, 13, {47, 22, 24, -42, 66, -21, 21, 41, 84, -8, 0, 59, 12, 62, -4, -106, -118, -42, 61, 71, 81, -67, -81, -78, -56, -110, -31, -21, -71, -119, -6, 44, -111, -56, 96, -51, 48, 61, -82, -72, 13, -106, -64, 96, -114, -30, -69, -72, 56, -98, 66, -25, 61, -104, -62, 21, 58, -42, 36, 89, -10, 0, -126, 38, }, }, }; // image
png_image *v0 = malloc(sizeof v0_tmp);
memcpy(v0, v0_tmp, sizeof v0_tmp);
png_image *v1 = v0; // image
i8 v2_tmp[] = {-119, 80, 78, 71, 13, 10, 26, 10, 0, 1, 0, 13, 122, 72, 68, 82, 0, 0, 0, 32, 0, 0, 0, 32, 8, 3, 0, 0, 0, 68, -92, -118, -58, 0, 0, 0, -53, 105, 67, 67, 80, 102, 111, 111, 0, 0, 40, -111, 99, 96, 96, 60, -109, 88, 80, -112, -60, 36, -64, -64, 32, 110, 105, 108, 20, -28, -18, -92, 16, 17, 25, -91, -64, -128, 4, 18, -109, -117, 11, 28, 3, 2, 124, 24, 112, -126, 109, -41, 24, 24, 65, -12, 101, 93, -112, 89, -72, -43, 97, 5, -100, 41, -87, -59, -55, 64, -6, 3, 16, -89, -107, -105, 20, -108, 48, 48, 48, 70, 0, -39, 34, 74, -39, 96, 54, -56, 60, -111, 34, -96, -93, -128, -20, 6, 16, 59, 29, -62, -98, 2, 86, 3, 97, -81, 2, -85, -119, 96, 114, 6, -78, -9, 1, -39, 124, 73, 72, -20, 116, 36, 54, -44, 46, 16, -32, -15, -55, -52, 75, 77, 44, 82, 40, 6, -6, -103, 68, 39, 19, 6, -120, 48, -4, 28, 8, 14, 27, 70, -79, 51, -24, -31, -118, -86, 46, 127, 17, 3, -125, -59, 87, 6, 6, -26, 9, 8, -79, -92, -103, 12, 12, -37, 91, 25, 24, 36, 110, 33, -60, 84, 22, 48, 48, -16, -73, 48, 48, 108, 59, -97, 92, 90, 84, 6, 53, -122, 17, 100, 5, 0, 19, 117, 57, -25, 7, -91, 69, -121, 0, 0, 0, 15, 80, 76, 84, 69, 102, -52, -52, -1, -1, -1, 0, 0, 0, 51, -103, 102, -103, -1, -52, 62, 76, -81, 21, 0, 0, 0, 25, 116, 69, 88, 116, 83, 111, 102, 116, 119, 97, 114, 101, 0, 65, 100, 111, 98, 101, 32, 73, 109, 97, 103, 101, 82, 101, 97, 100, 121, 113, -55, 101, 60, 0, 0, 0, 91, 73, 68, 65, 84, 56, -53, -35, -109, 65, 10, -128, 64, 12, 3, 51, -51, -2, -1, -51, 30, 84, -40, 69, -37, 122, -15, -96, 115, -51, 64, 32, -76, -94, 65, 16, 5, 32, 98, -28, 40, 16, 49, -108, -30, -97, 10, 0, -107, 112, -84, -101, 10, -128, 61, 27, 87, -63, -106, -64, 105, -59, -98, 23, -62, 89, 83, 8, 75, 126, 47, 76, 121, 34, 52, 75, -70, 17, -106, 33, -33, -87, -8, -20, -55, -55, 57, -15, -28, 121, 27, 54, -46, 102, 3, 53, 127, -53, 12, 109, 0, 0, 0, 0, 73, 69, 78, 68, -82, 66, 96, -126, 0, }; // memory
i8 *v2 = malloc(sizeof v2_tmp);
memcpy(v2, v2_tmp, sizeof v2_tmp);
i8 *v3 = v2; // memory
usize v4 = 428; // size
i32 v5 = png_image_begin_read_from_memory(v1, v3, v4); // $relative
char* path_v6 = "file_file";
char* v6 = path_v6; // file
i8 v7_tmp[] = {-31, -70, 76, 74, 50, 74, 97, -5, -28, -21, 77, 78, -103, -29, -108, -82, -76, -92, 61, -100, 3, -91, 59, 42, 73, 51, 40, 98, -23, -56, -69, 31, -42, -75, 0, -118, -114, 99, 62, -44, 33, -69, 124, -11, 63, 120, -63, -43, 12, -38, -43, 77, 93, 107, 62, -68, 0, }; // buffer
i8 *v7 = malloc(sizeof v7_tmp);
memcpy(v7, v7_tmp, sizeof v7_tmp);
i8 *v8 = v7; // buffer
i8 v9_tmp[] = {46, 3, -22, -100, 0, -45, -110, -32, 24, -97, -30, -124, -62, 31, -121, 28, 19, -58, -84, -33, 52, 31, -6, 86, -56, -101, -90, 36, -39, -42, 127, 29, -26, -21, -6, -25, 124, 66, -90, -23, -31, -105, -53, 65, 78, 63, -37, -15, -44, -10, -94, -1, 123, -7, -7, -81, -88, 52, 72, 115, -98, -125, 102, 98, -30, 44, -102, 126, 79, -35, 44, -57, 0, }; // colormap
i8 *v9 = malloc(sizeof v9_tmp);
memcpy(v9, v9_tmp, sizeof v9_tmp);
i8 *v10 = v9; // colormap
i32 v11 = 0; // convert_to_8bit
i32 v12 = 0; // row_stride
i32 v13 = png_image_write_to_file(v1, v6, v11, v8, v12, v10); // $relative
}
We can set the width in the png_image structure directly, and also we may get an zero width image by the API invoking of png_image_begin_read_from_memory, as the example shown.
This is a bug in your application. row_stride is passed to all those functions. It has to be correct.
If there is a bug in the read code please report it separately.