diff --git a/libretro-common/formats/png/rpng_decode_common.h b/libretro-common/formats/png/rpng_decode_common.h index 7d5afa5a92..2b55a8467c 100644 --- a/libretro-common/formats/png/rpng_decode_common.h +++ b/libretro-common/formats/png/rpng_decode_common.h @@ -46,6 +46,75 @@ static enum png_chunk_type png_chunk_type(const struct png_chunk *chunk) return PNG_CHUNK_NOOP; } +static bool png_process_ihdr(struct png_ihdr *ihdr) +{ + unsigned i; + bool ret = true; + + switch (ihdr->color_type) + { + case PNG_IHDR_COLOR_RGB: + case PNG_IHDR_COLOR_GRAY_ALPHA: + case PNG_IHDR_COLOR_RGBA: + if (ihdr->depth != 8 && ihdr->depth != 16) + GOTO_END_ERROR(); + break; + case PNG_IHDR_COLOR_GRAY: + { + static const unsigned valid_bpp[] = { 1, 2, 4, 8, 16 }; + bool correct_bpp = false; + + for (i = 0; i < ARRAY_SIZE(valid_bpp); i++) + { + if (valid_bpp[i] == ihdr->depth) + { + correct_bpp = true; + break; + } + } + + if (!correct_bpp) + GOTO_END_ERROR(); + } + break; + case PNG_IHDR_COLOR_PLT: + { + static const unsigned valid_bpp[] = { 1, 2, 4, 8 }; + bool correct_bpp = false; + + for (i = 0; i < ARRAY_SIZE(valid_bpp); i++) + { + if (valid_bpp[i] == ihdr->depth) + { + correct_bpp = true; + break; + } + } + + if (!correct_bpp) + GOTO_END_ERROR(); + } + break; + default: + GOTO_END_ERROR(); + } + +#ifdef RPNG_TEST + fprintf(stderr, "IHDR: (%u x %u), bpc = %u, palette = %s, color = %s, alpha = %s, adam7 = %s.\n", + ihdr->width, ihdr->height, + ihdr->depth, ihdr->color_type == PNG_IHDR_COLOR_PLT ? "yes" : "no", + ihdr->color_type & PNG_IHDR_COLOR_RGB ? "yes" : "no", + ihdr->color_type & PNG_IHDR_COLOR_GRAY_ALPHA ? "yes" : "no", + ihdr->interlace == 1 ? "yes" : "no"); +#endif + + if (ihdr->compression != 0) + GOTO_END_ERROR(); + +end: + return ret; +} + static void png_reverse_filter_copy_line_rgb(uint32_t *data, const uint8_t *decoded, unsigned width, unsigned bpp) { diff --git a/libretro-common/formats/png/rpng_decode_fbio.c b/libretro-common/formats/png/rpng_decode_fbio.c index 992b9b8d7a..c311260cf2 100644 --- a/libretro-common/formats/png/rpng_decode_fbio.c +++ b/libretro-common/formats/png/rpng_decode_fbio.c @@ -85,7 +85,7 @@ static bool png_parse_ihdr_fio(FILE *file, return false; if (chunk->size != 13) - GOTO_END_ERROR(); + return false; ihdr->width = dword_be(chunk->data + 0); ihdr->height = dword_be(chunk->data + 4); @@ -96,76 +96,9 @@ static bool png_parse_ihdr_fio(FILE *file, ihdr->interlace = chunk->data[12]; if (ihdr->width == 0 || ihdr->height == 0) - GOTO_END_ERROR(); + return false; - switch (ihdr->color_type) - { - case PNG_IHDR_COLOR_RGB: - case PNG_IHDR_COLOR_GRAY_ALPHA: - case PNG_IHDR_COLOR_RGBA: - if (ihdr->depth != 8 && ihdr->depth != 16) - GOTO_END_ERROR(); - break; - case PNG_IHDR_COLOR_GRAY: - { - static const unsigned valid_bpp[] = { 1, 2, 4, 8, 16 }; - bool correct_bpp = false; - - for (i = 0; i < ARRAY_SIZE(valid_bpp); i++) - { - if (valid_bpp[i] == ihdr->depth) - { - correct_bpp = true; - break; - } - } - - if (!correct_bpp) - GOTO_END_ERROR(); - } - break; - case PNG_IHDR_COLOR_PLT: - { - static const unsigned valid_bpp[] = { 1, 2, 4, 8 }; - bool correct_bpp = false; - - for (i = 0; i < ARRAY_SIZE(valid_bpp); i++) - { - if (valid_bpp[i] == ihdr->depth) - { - correct_bpp = true; - break; - } - } - - if (!correct_bpp) - GOTO_END_ERROR(); - } - break; - default: - GOTO_END_ERROR(); - } - -#ifdef RPNG_TEST - fprintf(stderr, "IHDR: (%u x %u), bpc = %u, palette = %s, color = %s, alpha = %s, adam7 = %s.\n", - ihdr->width, ihdr->height, - ihdr->depth, ihdr->color_type == PNG_IHDR_COLOR_PLT ? "yes" : "no", - ihdr->color_type & PNG_IHDR_COLOR_RGB ? "yes" : "no", - ihdr->color_type & PNG_IHDR_COLOR_GRAY_ALPHA ? "yes" : "no", - ihdr->interlace == 1 ? "yes" : "no"); -#endif - - if (ihdr->compression != 0) - GOTO_END_ERROR(); - -#if 0 - if (ihdr->interlace != 0) /* No Adam7 supported. */ - GOTO_END_ERROR(); -#endif - -end: - png_free_chunk(chunk); - return ret; + return true; } static bool png_append_idat_fio(FILE *file, @@ -262,7 +195,16 @@ bool rpng_load_image_argb(const char *path, uint32_t **data, GOTO_END_ERROR(); if (!png_parse_ihdr_fio(file, &chunk, &rpng.ihdr)) + { + png_free_chunk(&chunk); GOTO_END_ERROR(); + } + + if (!png_process_ihdr(&rpng.ihdr)) + { + png_free_chunk(&chunk); + GOTO_END_ERROR(); + } rpng.has_ihdr = true; break; diff --git a/libretro-common/formats/png/rpng_decode_fnbio.c b/libretro-common/formats/png/rpng_decode_fnbio.c index 0dad7bd1f1..b4d90a86ff 100644 --- a/libretro-common/formats/png/rpng_decode_fnbio.c +++ b/libretro-common/formats/png/rpng_decode_fnbio.c @@ -56,7 +56,6 @@ static bool read_chunk_header(uint8_t *buf, struct png_chunk *chunk) static bool png_parse_ihdr(uint8_t *buf, struct png_ihdr *ihdr) { - unsigned i; bool ret = true; buf += 4 + 4; @@ -70,75 +69,9 @@ static bool png_parse_ihdr(uint8_t *buf, ihdr->interlace = buf[12]; if (ihdr->width == 0 || ihdr->height == 0) - GOTO_END_ERROR(); + return false; - switch (ihdr->color_type) - { - case PNG_IHDR_COLOR_RGB: - case PNG_IHDR_COLOR_GRAY_ALPHA: - case PNG_IHDR_COLOR_RGBA: - if (ihdr->depth != 8 && ihdr->depth != 16) - GOTO_END_ERROR(); - break; - case PNG_IHDR_COLOR_GRAY: - { - static const unsigned valid_bpp[] = { 1, 2, 4, 8, 16 }; - bool correct_bpp = false; - - for (i = 0; i < ARRAY_SIZE(valid_bpp); i++) - { - if (valid_bpp[i] == ihdr->depth) - { - correct_bpp = true; - break; - } - } - - if (!correct_bpp) - GOTO_END_ERROR(); - } - break; - case PNG_IHDR_COLOR_PLT: - { - static const unsigned valid_bpp[] = { 1, 2, 4, 8 }; - bool correct_bpp = false; - - for (i = 0; i < ARRAY_SIZE(valid_bpp); i++) - { - if (valid_bpp[i] == ihdr->depth) - { - correct_bpp = true; - break; - } - } - - if (!correct_bpp) - GOTO_END_ERROR(); - } - break; - default: - GOTO_END_ERROR(); - } - -#ifdef RPNG_TEST - fprintf(stderr, "IHDR: (%u x %u), bpc = %u, palette = %s, color = %s, alpha = %s, adam7 = %s.\n", - ihdr->width, ihdr->height, - ihdr->depth, ihdr->color_type == PNG_IHDR_COLOR_PLT ? "yes" : "no", - ihdr->color_type & PNG_IHDR_COLOR_RGB ? "yes" : "no", - ihdr->color_type & PNG_IHDR_COLOR_GRAY_ALPHA ? "yes" : "no", - ihdr->interlace == 1 ? "yes" : "no"); -#endif - - if (ihdr->compression != 0) - GOTO_END_ERROR(); - -#if 0 - if (ihdr->interlace != 0) /* No Adam7 supported. */ - GOTO_END_ERROR(); -#endif - -end: - return ret; + return true; } static bool png_realloc_idat(const struct png_chunk *chunk, struct idat_buffer *buf) @@ -209,6 +142,9 @@ bool rpng_nbio_load_image_argb_iterate(uint8_t *buf, struct rpng_t *rpng) if (!png_parse_ihdr(buf, &rpng->ihdr)) return false; + if (!png_process_ihdr(&rpng->ihdr)) + return false; + rpng->has_ihdr = true; break;