diff --git a/ChangeLog b/ChangeLog index bf7ae1f7..201d2b00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,86 @@ +2019-12-19 Hayaki Saito + + * src/fromsixel.c: sixel decoder: extend image width and height separately + +2019-12-18 Hayaki Saito + + * Makefile.in, configure, configure.ac, package.json: Bump the package + version + + * ChangeLog: Update ChangeLog + + * src/fromsixel.c: Suppress gcc -Wsign-conversion warnings + + * README.md: Update README + + * src/stb_image.h: Raise an error instead of assert() when wrong color mask + is detected (#89) + + * src/fromsixel.c: Prevent integer overflow reported in #118, thanks to + @SuhwanSong + +2019-12-17 Hayaki Saito + + * src/fromsixel.c: Fix typo + + * converters/sixel2png.c: sixel2png: fix misssing error handling + + * src/tosixel.c: Add additional error message for SIXEL_BAD_INTEGER_OVERFLOW + + * src/frompnm.c: Fix for infinite recursive loop problem in load_pnm() + (#85), Thanks to @Loginsoft-Research + + * src/loader.c: Try to suppress gcc -Wclobbered warnings again + + * Makefile.in, config.h.in, configure, configure.ac, src/loader.c: Check + availability of -Wclobbered + + * src/loader.c: Try to suppress gcc -Wclobbered warnings again + + * Makefile.in, src/loader.c: Suppress gcc -Werror=clobbered warnings + +2019-12-16 Hayaki Saito + + * src/fromsixel.c: Add error message for 1377517 + + * src/fromsixel.c: Make safe_addition_for_params() as a static function + + * Makefile.in, src/fromsixel.c: Add error message for 9c013f2 + + * README.md: Update README: add more projects using sixels + + * src/tosixel.c: Fix access violation problem on high color mode (#116), + Thanks to SuhwanSong + + * src/dither.c: Use SIXEL_PALETTE_MAX instead of 256 + + * src/fromsixel.c: Use SIXEL_PALETTE_MAX instead of 256 + +2019-12-15 Hayaki Saito + + * src/fromsixel.c: Add invalid parameter check at image_buffer_init() / + image_buffer_resize() (#107) + + * Makefile.in, src/fromsixel.c: Avoid huge memory allocation caused by + integer overflow problems + + * src/loader.c: Handle libpng error message (#73), thanks to HongxuChen + + * src/dither.c: Avoid illegal memory access problem with 1 color paletted + png(#73), Thanks to HongxuChen. + + * README.md: Update README + + * README.md: Update README + + * configure, configure.ac, package.json: Bump version + + * README.md, converters/img2sixel.1: Update contributers section + + * NEWS: Update NEWS + + * ChangeLog: Update ChangeLog + 2019-12-13 Hayaki Saito * src/loader.c: Suppress glib deprecated warnings diff --git a/NEWS b/NEWS index c375ee33..0724be4b 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,32 @@ ------------------------------ What's new in libsixel-1.8 ? ------------------------------ +* Security fix for CVE-2019-11024 (#85), recursive loop problem, + reported by @Loginsoft-Research. + +* Security fix for #73, illegal memory access problem, + reported by @HongxuChen. + +* Security fix for #89, core dumped issue, + reported by @niugx. + +* Security fix for #107, large memory allocation problem, + reported by @cuanduo. + +* Security fix for #114, heap-buffer-overflow problem, + reported by @SuhwanSong. + +* Security fix for #116, heap-buffer-overflow problem, + reported by @SuhwanSong. + +* Security fix for #118, heap-buffer-overflow problem, + reported by @SuhwanSong. + +* Security fix for #121, heap-buffer-overflow problem, + reported by @gutiniao + +* Security fix for #73, illegal memory access problem, + reported by @HongxuChen. * Security fix for CVE-2018-19757 (#79), NULL pointer dereference problem, reported by @nluedtke and fixed by @knok (#91, #94). diff --git a/README.md b/README.md index 7053e821..eafad432 100644 --- a/README.md +++ b/README.md @@ -299,6 +299,9 @@ $ xterm -xrm "XTerm*decTerminalID: vt340" -xrm "XTerm*numColorRegisters: 256" - cancer [https://github.com/meh/cancer/](https://github.com/meh/cancer) +- MacTerm + [https://github.com/kmgrant/macterm](https://github.com/kmgrant/macterm) + - wezterm [https://github.com/wez/wezterm](https://github.com/wez/wezterm) @@ -311,6 +314,15 @@ $ xterm -xrm "XTerm*decTerminalID: vt340" -xrm "XTerm*numColorRegisters: 256" - st-sixel [https://github.com/galatolofederico/st-sixel](https://github.com/galatolofederico/st-sixel) +- DomTerm + [https://github.com/PerBothner/DomTerm](https://github.com/PerBothner/DomTerm) + +- yaft-cocoa + [https://github.com/uobikiemukot/yaft-cocoa](https://github.com/uobikiemukot/yaft-cocoa) + +- toyterm + [https://github.com/algon-320/toyterm](https://github.com/algon-320/toyterm) + ## Install @@ -1510,3 +1522,25 @@ We are greatly inspired by the quality of ImageMagick and added some resampling - [hpjansson/chafa](https://github.com/hpjansson/chafa) - [m-j-w/TerminalGraphics.jl](https://github.com/m-j-w/TerminalGraphics.jl) + +- [MIC-DKFZ/niicat](https://github.com/MIC-DKFZ/niicat) + +- [libretro/RetroArch](https://github.com/libretro/RetroArch) + +- [jerch/node-sixel](https://github.com/jerch/node-sixel) + +- [nikiroo/fanfix](https://github.com/nikiroo/fanfix) + +- [mattn/longcat](https://github.com/mattn/longcat) + +- [ismail-yilmaz/upp-components/CtrlLib/Terminal/](https://github.com/ismail-yilmaz/upp-components/tree/master/CtrlLib/Terminal) + +- [schrmh/pdfgrepSIXEL](schrmh/pdfgrepSIXEL) + +- [ar90n/teimpy](https://github.com/ar90n/teimpy) + +- [vifm/vifm](https://github.com/vifm/vifm) + +- [ktye/iv](https://github.com/ktye/iv/commit/815e06ed776dde3deca0fdba35da5f0b431a69bf) + +- [Delta/longdog](https://github.com/0Delta/longdog) diff --git a/config.h.in b/config.h.in index 6514d2f5..86b8be8a 100644 --- a/config.h.in +++ b/config.h.in @@ -75,6 +75,9 @@ don't. */ #undef HAVE_DECL_SIGTERM +/* define 1 if GCC supports -Wclobbered */ +#undef HAVE_DIAGNOSTIC_CLOBBERED + /* define 1 if GCC supports -Wdeprecated-declarations */ #undef HAVE_DIAGNOSTIC_DEPRECATED_DECLARATIONS diff --git a/configure b/configure index aee2ddb2..7b3c3288 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sixel 1.8.3. +# Generated by GNU Autoconf 2.69 for sixel 1.8.4. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sixel' PACKAGE_TARNAME='sixel' -PACKAGE_VERSION='1.8.3' -PACKAGE_STRING='sixel 1.8.3' +PACKAGE_VERSION='1.8.4' +PACKAGE_STRING='sixel 1.8.4' PACKAGE_BUGREPORT='saitoha@me.com' PACKAGE_URL='' @@ -1393,7 +1393,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sixel 1.8.3 to adapt to many kinds of systems. +\`configure' configures sixel 1.8.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1463,7 +1463,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sixel 1.8.3:";; + short | recursive ) echo "Configuration of sixel 1.8.4:";; esac cat <<\_ACEOF @@ -1612,7 +1612,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sixel configure 1.8.3 +sixel configure 1.8.4 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2027,7 +2027,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sixel $as_me 1.8.3, which was +It was created by sixel $as_me 1.8.4, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2970,7 +2970,7 @@ fi # Define the identity of the package. PACKAGE='sixel' - VERSION='1.8.3' + VERSION='1.8.4' cat >>confdefs.h <<_ACEOF @@ -13635,6 +13635,37 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$saved_cflags" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Wclobbered" >&5 +$as_echo_n "checking if $CC supports -Wclobbered... " >&6; } + saved_cflags="$CFLAGS" + CFLAGS="-Wclobbered -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + AM_CFLAGS="$AM_CFLAGS -Wclobbered" + +$as_echo "#define HAVE_DIAGNOSTIC_CLOBBERED 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$saved_cflags" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Bsymbolic" >&5 $as_echo_n "checking if $CC supports -Bsymbolic... " >&6; } saved_cflags="$CFLAGS" @@ -16373,7 +16404,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sixel $as_me 1.8.3, which was +This file was extended by sixel $as_me 1.8.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16439,7 +16470,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sixel config.status 1.8.3 +sixel config.status 1.8.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index ba80232b..5e00b38d 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) LT_PREREQ([2.4]) -AC_INIT([sixel], [1.8.3], [saitoha@me.com]) +AC_INIT([sixel], [1.8.4], [saitoha@me.com]) LS_LT_CURRENT=1 LS_LT_REVISION=6 LS_LT_AGE=0 @@ -208,6 +208,9 @@ LS_CHECK_CFLAG([-Wswitch-default], LS_CHECK_CFLAG([-Wunused-function], [AM_CFLAGS="$AM_CFLAGS -Wunused-function" AC_DEFINE(HAVE_DIAGNOSTIC_UNUSED_FUNCTION, 1, [define 1 if GCC supports -Wunused-function])]) +LS_CHECK_CFLAG([-Wclobbered], + [AM_CFLAGS="$AM_CFLAGS -Wclobbered" + AC_DEFINE(HAVE_DIAGNOSTIC_CLOBBERED, 1, [define 1 if GCC supports -Wclobbered])]) LS_CHECK_CFLAG([-Bsymbolic], [AM_CFLAGS="$AM_CFLAGS -Bsymbolic" AC_DEFINE(HAVE_BSYMBOLIC, 1, [define 1 if GCC supports -Bsymbolic])]) diff --git a/converters/sixel2png.c b/converters/sixel2png.c index 9ea97706..24a68b3c 100644 --- a/converters/sixel2png.c +++ b/converters/sixel2png.c @@ -224,6 +224,9 @@ main(int argc, char *argv[]) } status = sixel_decoder_decode(decoder); + if (SIXEL_FAILED(status)) { + goto error; + } goto end; argerr: diff --git a/package.json b/package.json index a2383287..bc95007f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "libsixel", - "version": "1.8.3", + "version": "1.8.4", "repo": "saitoha/libsixel", "description": "A lightweight, fast implementation of DEC SIXEL graphics codec", "keywords": ["terminal", "graphics", "image", "sixel"], diff --git a/src/dither.c b/src/dither.c index 72251d78..fc33bac0 100644 --- a/src/dither.c +++ b/src/dither.c @@ -280,13 +280,17 @@ sixel_dither_new( } if (ncolors < 0) { - ncolors = 256; + ncolors = SIXEL_PALETTE_MAX; quality_mode = SIXEL_QUALITY_HIGHCOLOR; } else { if (ncolors > SIXEL_PALETTE_MAX) { - ncolors = 256; - } else if (ncolors < 2) { - ncolors = 2; + status = SIXEL_BAD_INPUT; + ncolors = SIXEL_PALETTE_MAX; + } else if (ncolors < 1) { + status = SIXEL_BAD_INPUT; + sixel_helper_set_additional_message( + "sixel_dither_new: palette colors must be more than 0"); + goto end; } quality_mode = SIXEL_QUALITY_LOW; } diff --git a/src/frompnm.c b/src/frompnm.c index 86d0c039..de737661 100644 --- a/src/frompnm.c +++ b/src/frompnm.c @@ -36,13 +36,15 @@ pnm_get_line(unsigned char *p, unsigned char *end, unsigned char *line) int n; do { + /* read the line */ for (n = 0 ; p < end && *p >= ' '; p++) { if (n < 255) { line[n++] = *p; } } - if (p < end && *p == '\n') { + /* skip invald characters */ + if (p < end && *p < ' ') { p++; } diff --git a/src/fromsixel.c b/src/fromsixel.c index e0332ae6..202173e3 100644 --- a/src/fromsixel.c +++ b/src/fromsixel.c @@ -231,7 +231,39 @@ image_buffer_init( int g; int b; - size = (size_t)(width * height) * sizeof(unsigned char); + /* check parameters */ + if (width <= 0) { + sixel_helper_set_additional_message( + "image_buffer_init: an invalid width parameter detected."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (height <= 0) { + sixel_helper_set_additional_message( + "image_buffer_init: an invalid width parameter detected."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (height > SIXEL_HEIGHT_LIMIT) { + sixel_helper_set_additional_message( + "image_buffer_init: given height parameter is too huge."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (width > SIXEL_WIDTH_LIMIT) { + sixel_helper_set_additional_message( + "image_buffer_init: given width parameter is too huge."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (height > SIXEL_HEIGHT_LIMIT) { + sixel_helper_set_additional_message( + "image_buffer_init: given height parameter is too huge."); + status = SIXEL_BAD_INPUT; + goto end; + } + + size = (size_t)(width) * (size_t)height * sizeof(unsigned char); image->width = width; image->height = height; image->data = (unsigned char *)sixel_allocator_malloc(allocator, size); @@ -289,7 +321,39 @@ image_buffer_resize( int n; int min_height; - size = (size_t)(width * height); + /* check parameters */ + if (width <= 0) { + sixel_helper_set_additional_message( + "image_buffer_init: an invalid width parameter detected."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (height <= 0) { + sixel_helper_set_additional_message( + "image_buffer_init: an invalid width parameter detected."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (height > SIXEL_HEIGHT_LIMIT) { + sixel_helper_set_additional_message( + "image_buffer_init: given height parameter is too huge."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (width > SIXEL_WIDTH_LIMIT) { + sixel_helper_set_additional_message( + "image_buffer_init: given width parameter is too huge."); + status = SIXEL_BAD_INPUT; + goto end; + } + if (height > SIXEL_HEIGHT_LIMIT) { + sixel_helper_set_additional_message( + "image_buffer_init: given height parameter is too huge."); + status = SIXEL_BAD_INPUT; + goto end; + } + + size = (size_t)width * (size_t)height; alt_buffer = (unsigned char *)sixel_allocator_malloc(allocator, size); if (alt_buffer == NULL || size == 0) { /* free source image */ @@ -305,28 +369,28 @@ image_buffer_resize( if (width > image->width) { /* if width is extended */ for (n = 0; n < min_height; ++n) { /* copy from source image */ - memcpy(alt_buffer + width * n, - image->data + image->width * n, + memcpy(alt_buffer + (size_t)width * (size_t)n, + image->data + (size_t)image->width * (size_t)n, (size_t)image->width); /* fill extended area with background color */ - memset(alt_buffer + width * n + image->width, + memset(alt_buffer + (size_t)width * (size_t)n + (size_t)image->width, bgindex, (size_t)(width - image->width)); } } else { for (n = 0; n < min_height; ++n) { /* copy from source image */ - memcpy(alt_buffer + width * n, - image->data + image->width * n, + memcpy(alt_buffer + (size_t)width * (size_t)n, + image->data + (size_t)image->width * (size_t)n, (size_t)width); } } if (height > image->height) { /* if height is extended */ /* fill extended area with background color */ - memset(alt_buffer + width * image->height, + memset(alt_buffer + (size_t)width * (size_t)image->height, bgindex, - (size_t)(width * (height - image->height))); + (size_t)width * (size_t)(height - image->height)); } /* free source image */ @@ -368,17 +432,28 @@ parser_context_init(parser_context_t *context) return status; } -SIXELSTATUS safe_addition_for_params(parser_context_t *context, unsigned char *p){ + +static SIXELSTATUS +safe_addition_for_params(parser_context_t *context, unsigned char *p) +{ + SIXELSTATUS status = SIXEL_FALSE; int x; x = *p - '0'; /* 0 <= x <= 9 */ if ((context->param > INT_MAX / 10) || (x > INT_MAX - context->param * 10)) { - return SIXEL_BAD_INTEGER_OVERFLOW; + status = SIXEL_BAD_INTEGER_OVERFLOW; + sixel_helper_set_additional_message( + "safe_addition_for_params: ingeger overflow detected."); + goto end; } context->param = context->param * 10 + x; - return SIXEL_OK; + status = SIXEL_OK; + +end: + return status; } + /* convert sixel data into indexed pixel bytes and palette data */ SIXELAPI SIXELSTATUS sixel_decode_raw_impl( @@ -397,7 +472,7 @@ sixel_decode_raw_impl( int sx; int sy; int c; - int pos; + size_t pos; unsigned char *p0 = p; while (p < p0 + len) { @@ -569,13 +644,18 @@ sixel_decode_raw_impl( break; default: if (*p >= '?' && *p <= '~') { /* sixel characters */ - if (image->width < (context->pos_x + context->repeat_count) || image->height < (context->pos_y + 6)) { - sx = image->width * 2; - sy = image->height * 2; - while (sx < (context->pos_x + context->repeat_count) || sy < (context->pos_y + 6)) { - sx *= 2; - sy *= 2; - } + + sx = image->width; + while (sx < context->pos_x + context->repeat_count) { + sx *= 2; + } + + sy = image->height; + while (sy < context->pos_y + 6) { + sy *= 2; + } + + if (sx > image->width || sy > image->height) { status = image_buffer_resize(image, sx, sy, context->bgindex, allocator); if (SIXEL_FAILED(status)) { goto end; @@ -599,7 +679,7 @@ sixel_decode_raw_impl( if (context->repeat_count <= 1) { for (i = 0; i < 6; i++) { if ((bits & sixel_vertical_mask) != 0) { - pos = image->width * (context->pos_y + i) + context->pos_x; + pos = (size_t)image->width * (size_t)(context->pos_y + i) + (size_t)context->pos_x; image->data[pos] = context->color_index; if (context->max_x < context->pos_x) { context->max_x = context->pos_x; @@ -623,7 +703,7 @@ sixel_decode_raw_impl( c <<= 1; } for (y = context->pos_y + i; y < context->pos_y + i + n; ++y) { - memset(image->data + image->width * y + context->pos_x, + memset(image->data + (size_t)image->width * (size_t)y + (size_t)context->pos_x, context->color_index, (size_t)context->repeat_count); } @@ -753,8 +833,10 @@ sixel_decode_raw_impl( if (context->repeat_count == 0) { context->repeat_count = 1; } - if (context->repeat_count > 0xffff) { /* check too huge number */ + if (context->repeat_count > 0xffff) { /* check too huge number */ status = SIXEL_BAD_INPUT; + sixel_helper_set_additional_message( + "sixel_decode_raw_impl: detected too huge repeat parameter."); goto end; } context->state = PS_DECSIXEL; @@ -916,8 +998,10 @@ sixel_decode_raw( *ncolors = image.ncolors + 1; int alloc_size = *ncolors; - if (alloc_size < 256) // memory access range should be 0 <= 255 (in write_png_to_file) - alloc_size = 256; + if (alloc_size < SIXEL_PALETTE_MAX) { + /* memory access range should be 0 <= 255 */ + alloc_size = SIXEL_PALETTE_MAX; + } *palette = (unsigned char *)sixel_allocator_malloc(allocator, (size_t)(alloc_size * 3)); if (palette == NULL) { sixel_allocator_free(allocator, image.data); diff --git a/src/loader.c b/src/loader.c index 111daec9..034bb242 100644 --- a/src/loader.c +++ b/src/loader.c @@ -269,6 +269,15 @@ read_palette(png_structp png_ptr, } +/* libpng error handler */ +static void +png_error_callback(png_structp png_ptr, png_const_charp error_message) +{ + sixel_helper_set_additional_message(error_message); + longjmp(png_jmpbuf(png_ptr), (-1)); +} + + static SIXELSTATUS load_png(unsigned char /* out */ **result, unsigned char /* in */ *buffer, @@ -283,20 +292,38 @@ load_png(unsigned char /* out */ **result, int /* out */ *transparent, sixel_allocator_t /* in */ *allocator) { - SIXELSTATUS status = SIXEL_FALSE; + SIXELSTATUS status; sixel_chunk_t read_chunk; png_uint_32 bitdepth; png_uint_32 png_status; png_structp png_ptr; png_infop info_ptr; - unsigned char **rows = NULL; +#ifdef HAVE_DIAGNOSTIC_CLOBBERED +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wclobbered" +#endif + unsigned char **rows; png_color *png_palette = NULL; png_color_16 background; png_color_16p default_background; int i; int depth; - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#if USE_SETJMP && HAVE_SETJMP + if (setjmp(png_jmpbuf(png_ptr)) != 0) { + sixel_allocator_free(allocator, *result); + *result = NULL; + status = SIXEL_PNG_ERROR; + goto cleanup; + } +#endif /* HAVE_SETJMP */ + + status = SIXEL_FALSE; + rows = NULL; + *result = NULL; + + png_ptr = png_create_read_struct( + PNG_LIBPNG_VER_STRING, NULL, &png_error_callback, NULL); if (!png_ptr) { sixel_helper_set_additional_message( "png_create_read_struct() failed."); @@ -576,14 +603,7 @@ load_png(unsigned char /* out */ **result, } break; } -#if USE_SETJMP && HAVE_SETJMP - if (setjmp(png_jmpbuf(png_ptr))) { - sixel_allocator_free(allocator, *result); - *result = NULL; - status = SIXEL_PNG_ERROR; - goto cleanup; - } -#endif /* HAVE_SETJMP */ + png_read_image(png_ptr, rows); status = SIXEL_OK; @@ -594,6 +614,10 @@ load_png(unsigned char /* out */ **result, return status; } +#ifdef HAVE_DIAGNOSTIC_CLOBBERED +# pragma GCC diagnostic pop +#endif + # endif /* HAVE_PNG */ diff --git a/src/stb_image.h b/src/stb_image.h index 48c5f2ae..87960126 100644 --- a/src/stb_image.h +++ b/src/stb_image.h @@ -5051,7 +5051,7 @@ static int stbi__shiftsigned(int v, int shift, int bits) v >>= shift; STBI_ASSERT(v >= 0 && v < 256); v >>= (8-bits); - STBI_ASSERT(bits >= 0 && bits <= 8); + if (bits < 0 || bits > 8) return (0); /* error */ return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; } @@ -5280,12 +5280,16 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req int bpp = info.bpp; for (i=0; i < (int) s->img_x; ++i) { stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); - unsigned int a; - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + unsigned int r, g, b, a; + r = stbi__shiftsigned(v & mr, rshift, rcount); + g = stbi__shiftsigned(v & mg, gshift, gcount); + b = stbi__shiftsigned(v & mb, bshift, bcount); a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); all_a |= a; + if (!r || !g || !b || !a) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + out[z++] = STBI__BYTECAST(r); + out[z++] = STBI__BYTECAST(g); + out[z++] = STBI__BYTECAST(b); if (target == 4) out[z++] = STBI__BYTECAST(a); } } diff --git a/src/tosixel.c b/src/tosixel.c index 220940c1..c021501e 100644 --- a/src/tosixel.c +++ b/src/tosixel.c @@ -561,12 +561,18 @@ sixel_encode_body( for (x = 0; x < width; x++) { if (y > INT_MAX / width) { /* integer overflow */ + sixel_helper_set_additional_message( + "sixel_encode_body: integer overflow detected." + " (y > INT_MAX)"); status = SIXEL_BAD_INTEGER_OVERFLOW; goto end; } check_integer_overflow = y * width; if (check_integer_overflow > INT_MAX - x) { /* integer overflow */ + sixel_helper_set_additional_message( + "sixel_encode_body: integer overflow detected." + " (y * width > INT_MAX - x)"); status = SIXEL_BAD_INTEGER_OVERFLOW; goto end; } @@ -574,12 +580,18 @@ sixel_encode_body( if (pix >= 0 && pix < ncolors && pix != keycolor) { if (pix > INT_MAX / width) { /* integer overflow */ + sixel_helper_set_additional_message( + "sixel_encode_body: integer overflow detected." + " (pix > INT_MAX / width)"); status = SIXEL_BAD_INTEGER_OVERFLOW; goto end; } check_integer_overflow = pix * width; if (check_integer_overflow > INT_MAX - x) { /* integer overflow */ + sixel_helper_set_additional_message( + "sixel_encode_body: integer overflow detected." + " (pix * width > INT_MAX - x)"); status = SIXEL_BAD_INTEGER_OVERFLOW; goto end; } @@ -1419,7 +1431,7 @@ sixel_encode_highcolor( goto end; } } - if (dirty && mod_y == 5) { + if (dirty && (mod_y == 5 || y >= height)) { orig_height = height; if (output_count++ == 0) { @@ -1442,6 +1454,9 @@ sixel_encode_highcolor( if (SIXEL_FAILED(status)) { goto error; } + if (y >= orig_height) { + goto end; + } pixels -= (6 * width * 3); height = orig_height - height + 6; goto next; @@ -1452,6 +1467,7 @@ sixel_encode_highcolor( mod_y = 0; } } + goto next; end: