Skip to content
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

Division by zero error in png_image_write_main if Image width is zero #489

Open
hopper-vul opened this issue Aug 10, 2023 · 2 comments
Open

Comments

@hopper-vul
Copy link

hopper-vul commented Aug 10, 2023

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.

@hopper-vul hopper-vul changed the title Division by zero error error in png_image_write_main if Image width is zero Division by zero error in png_image_write_main if Image width is zero Aug 10, 2023
@jbowler
Copy link
Contributor

jbowler commented Dec 9, 2023

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.

@jbowler
Copy link
Contributor

jbowler commented Sep 22, 2024

png_image_write_init could check width and height for >0 and just return 0 if they are not. It can't output an error at that point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants