VYPR
Medium severity6.5NVD Advisory· Published Sep 14, 2021· Updated Apr 24, 2026

CVE-2020-21048

CVE-2020-21048

Description

An issue in the dither.c component of libsixel prior to v1.8.4 allows attackers to cause a denial of service (DOS) via a crafted PNG file.

Affected products

1

Patches

2
686d234ae20f

Merge branch 'release'

https://github.com/saitoha/libsixelHayaki SaitoDec 18, 2019via osv
15 files changed · +378 61
  • ChangeLog+83 0 modified
    @@ -1,3 +1,86 @@
    +2019-12-19  Hayaki Saito <saitoha@me.com>
    +
    +  * src/fromsixel.c: sixel decoder: extend image width and height separately
    +
    +2019-12-18  Hayaki Saito <saitoha@me.com>
    +
    +  * 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 <saitoha@me.com>
    +
    +  * 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 <saitoha@me.com>
    +
    +  * 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 <saitoha@me.com>
    +
    +  * 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 <saitoha@me.com>
     
       * src/loader.c: Suppress glib deprecated warnings
    
  • config.h.in+3 0 modified
    @@ -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
     
    
  • configure+41 10 modified
    @@ -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 <saitoha@me.com>.
     #
    @@ -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\\"
     
    
  • configure.ac+4 1 modified
    @@ -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])])
    
  • converters/sixel2png.c+3 0 modified
    @@ -224,6 +224,9 @@ main(int argc, char *argv[])
         }
     
         status = sixel_decoder_decode(decoder);
    +    if (SIXEL_FAILED(status)) {
    +        goto error;
    +    }
         goto end;
     
     argerr:
    
  • Makefile.in+2 2 modified
    @@ -192,8 +192,8 @@ CTAGS = ctags
     CSCOPE = cscope
     am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
     	$(srcdir)/libsixel.pc.in $(srcdir)/package.json.in.in \
    -	ChangeLog NEWS compile config.guess config.sub install-sh \
    -	ltmain.sh missing py-compile
    +	ChangeLog NEWS compile config.guess config.sub depcomp \
    +	install-sh ltmain.sh missing py-compile
     DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
     distdir = $(PACKAGE)-$(VERSION)
     top_distdir = $(distdir)
    
  • NEWS+26 0 modified
    @@ -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).
    
  • package.json+1 1 modified
    @@ -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"],
    
  • README.md+34 0 modified
    @@ -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)
    
  • src/dither.c+8 4 modified
    @@ -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;
         }
    
  • src/frompnm.c+3 1 modified
    @@ -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++;
             }
     
    
  • src/fromsixel.c+109 25 modified
    @@ -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);
    
  • src/loader.c+35 11 modified
    @@ -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 */
     
     
    
  • src/stb_image.h+9 5 modified
    @@ -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);
                 }
              }
    
  • src/tosixel.c+17 1 modified
    @@ -561,25 +561,37 @@ 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;
                 }
                 pix = pixels[check_integer_overflow + x];  /* color index */
                 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:
    
cb373ab6614c

Avoid illegal memory access problem with 1 color paletted png(#73),

https://github.com/saitoha/libsixelHayaki SaitoDec 15, 2019via nvd-ref
1 file changed · +6 2
  • src/dither.c+6 2 modified
    @@ -284,9 +284,13 @@ sixel_dither_new(
             quality_mode = SIXEL_QUALITY_HIGHCOLOR;
         } else {
             if (ncolors > SIXEL_PALETTE_MAX) {
    +            status = SIXEL_BAD_INPUT;
                 ncolors = 256;
    -        } else if (ncolors < 2) {
    -            ncolors = 2;
    +        } 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;
         }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.