diff --git a/.travis.yml b/.travis.yml index 29d306e4..8917bdb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,8 @@ matrix: env: XCC=clang HOST= PREFIX=/usr/local DEBUG="--enable-tests --enable-debug" WINE= LIBCURL=--without-libcurl JPEG=--without-jpeg PNG=--without-png - os: linux env: XCC=i686-w64-mingw32-gcc HOST="--host=i686-w64-mingw32" PREFIX="/usr/i686-w64-mingw32" DEBUG="--enable-tests --enable-debug" WINE=wine - - os: linux - env: XCC=i586-mingw32msvc-gcc HOST="--host=i586-mingw32msvc" PREFIX="/usr/i586-mingw32msvc" WINE=wine +# - os: linux +# env: XCC=i586-mingw32msvc-gcc HOST="--host=i586-mingw32msvc" PREFIX="/usr/i586-mingw32msvc" WINE=wine - os: linux env: XCC=x86_64-w64-mingw32-gcc HOST="--host=x86_64-w64-mingw32" PREFIX="/usr/x86_64-w64-mingw32" DEBUG="--enable-tests --enable-debug" WINE=wine64 - os: linux @@ -68,7 +68,7 @@ before_install: - "if [ x$TRAVIS_OS_NAME = xlinux -a x$XCC = xclang ]; then sudo apt-get install -qq clang; fi" - "if [ x$TRAVIS_OS_NAME = xlinux -a x$XCC = xgcc ]; then sudo apt-get install -qq gcc; fi" - "if [ x$TRAVIS_OS_NAME = xlinux -a x$XCC = xi686-w64-mingw32-gcc ]; then sudo apt-get install -qq gcc-mingw-w64-i686 binutils-mingw-w64-i686; fi" - - "if [ x$TRAVIS_OS_NAME = xlinux -a x$XCC = xi586-mingw32msvc-gcc ]; then sudo apt-get install -qq mingw32; fi" +# - "if [ x$TRAVIS_OS_NAME = xlinux -a x$XCC = xi586-mingw32msvc-gcc ]; then sudo apt-get install -qq mingw32; fi" - "if [ x$TRAVIS_OS_NAME = xlinux -a x$XCC = xx86_64-w64-mingw32-gcc ]; then sudo apt-get install -qq gcc-mingw-w64-x86-64 binutils-mingw-w64-x86-64; fi" - "if [ x$TRAVIS_OS_NAME = xlinux -a x$GCOV != x ]; then sudo apt-get install libyaml-dev; fi" - "if [ x$TRAVIS_OS_NAME = xosx -a x$GCOV != x ]; then brew install libyaml; fi" diff --git a/ChangeLog b/ChangeLog index 5c93331e..bf7ae1f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,186 @@ +2019-12-13 Hayaki Saito + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * src/loader.c: Suppress glib deprecated warnings + + * .travis.yml: Ammend fix for e18ebe6 + + * .travis.yml: Drop mingw32 build + + * .travis.yml: Drop mingw32 build + +2019-12-02 pwd + + * src/fromsixel.c: use function safe_addition_for_params to check integer + overflow + + * src/frompnm.c: fix issue that the width and the deps miss checks + + * include/sixel.h.in, src/status.c: define macro SIXEL_BAD_INTEGER_OVERFLOW + for integer + + * src/tosixel.c: check integer overflow in 'map[pix * width + x] |= (1 << + i);' + +2019-08-29 Takatsugu Nokubi + + * src/loader.c: check jpeg decoder error + + * src/fromsixel.c: check size, fix issue #83 + +2019-08-01 Takatsugu Nokubi + + * include/sixel.h.in, src/decoder.c: add limitation to width and height + +2019-07-25 Takatsugu Nokubi + + * src/fromsixel.c: position error check + +2019-07-24 Takatsugu Nokubi + + * src/fromsixel.c: prevent to access heap overflow + +2019-07-23 Takatsugu Nokubi + + * src/stb_image.h: assign default error message + +2019-07-08 Takatsugu Nokubi + + * src/allocator.c: Add malloc size check + + * src/fromsixel.c: size check + +2019-07-07 Takatsugu Nokubi + + * src/status.c: no op when message is NULL + +2018-08-06 Hayaki Saito + + * src/stb_image.h: stb_image: fix for #76 POC h050. detect bad PSD file. + +2018-08-05 Hayaki Saito + + * src/stb_image.h: stb_image: fix for #76 POC h010. detect bad PSD file + which has fake size declaration in its image header + + * src/stb_image.h: stb_image: fix for #76 POC h002. detect bad TGA file + which has fake size declaration in its image header + + * src/fromgif.c: GIF loader: fix for #76 POC h001. don't believe image size + declared in the header, use actual size. + https://github.com/saitoha/libsixel/issues/76 + +2018-08-03 Hayaki Saito + + * src/stb_image.h: Quickfix for issue #72: validate huffman code + https://github.com/saitoha/libsixel/issues/72 + +2018-08-02 Hayaki Saito + + * src/fromgif.c: gif loader: add some comments + + * src/fromgif.c: gif loader: check LZW code size (Issue #75) + +2018-07-23 Hayaki Saito + + * src/Makefile.am, src/Makefile.in: Amend travis build fixes again + + * src/Makefile.am, src/Makefile.in: Amend fix for travis build + + * src/Makefile.am, src/Makefile.in: Travis build fixes + + * NEWS: Update NEWS + + * README.md: Update README.md + + * README.md: Update README.md + + * README.md: Update README.md + + * Makefile.in, README.md, aclocal.m4, compile, config.guess, config.sub, + configure, configure.ac, converters/Makefile.in, depcomp, + include/Makefile.in, install-sh, missing, package.json, py-compile, + python/Makefile.in, src/Makefile.in, tools/Makefile.in: Bump version 1.8.2 + + * NEWS: Update NEWS + + * ChangeLog: Update ChangeLog + 2018-06-10 Hayaki Saito * converters/img2sixel.1: Fix a typo: a_dither -> x_dither(issue #66) diff --git a/NEWS b/NEWS index b63bce22..c375ee33 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,47 @@ ------------------------------ What's new in libsixel-1.8 ? ------------------------------ + +* Security fix for CVE-2018-19757 (#79), NULL pointer dereference problem, + reported by @nluedtke and fixed by @knok (#91, #94). + +* Security fix for CVE-2018-19762 (#81), heap-based buffer overflow problem, + reported by @nluedtke and fixed by @knok (#92). + +* Security fix for CVE-2018-19756 (#80), heap-based buffer over-read problem, + reported by @nluedtke and fixed by @knok (#93). + +* Security fix for CVE-2018-19763 (#82), heap-based buffer over-read problem, + reported by @nluedtke and fixed by @knok (#95). + +* Security fix for CVE-2018-19761, illegal address access, fixed by @knok (#96). + +* Security fix for CVE-2018-19759, heap-based buffer over-read problem, fixed by @knok (#98). + +* Security fix for CVE-2018-3753 (#83), infinite loop problem, + reported by @cool-tomato and fixed by @knok (#99). + +* Security fix for CVE-2018-19759 (#102), + heap-based buffer over-read that will cause a denial of service. + reported and fixed by @YourButterfly. (#106) + +* Security fix for CVE-2019-19635 (#103), heap-based buffer overflow, + reported and fixed by @YourButterfly. (#106) + +* Security fix for CVE-2019-19636 (#104) and CVE-2019-19637 (#105), integer overflow problem. + reported and fixed by @YourButterfly. (#106) + +* gif loader: check LZW code size (Issue #75), Thanks to @HongxuChen. + https://github.com/saitoha/libsixel/commit/7808a06b88c11dbc502318cdd51fa374f8cd47ee + +* core: Fix a global-buffer-overflow problem (Issue #72), Thanks to @fgeek. + https://github.com/saitoha/libsixel/commit/c868b59ec89bdb24c42a0de89e5319a989076c66 + +* core: Fix unexpected hangs/performance issues (Issue #76), Thanks to @HongxuChen. + https://github.com/saitoha/libsixel/commit/88561b7a810017b91d26b6273323dde4b6f9b273 + https://github.com/saitoha/libsixel/commit/2d3d9ffe8ab886b7bc670fd896d63c628436cc66 + https://github.com/saitoha/libsixel/commit/c9363cd1d5929e1d721af9f09633061dfa8152fe + * core: Upgrade stb_image to 2.19. * core: Introduce new dithering method, a_dither / x_dither (http://pippin.gimp.org/a_dither/). diff --git a/README.md b/README.md index 1b383837..7053e821 100644 --- a/README.md +++ b/README.md @@ -299,6 +299,18 @@ $ xterm -xrm "XTerm*decTerminalID: vt340" -xrm "XTerm*numColorRegisters: 256" - cancer [https://github.com/meh/cancer/](https://github.com/meh/cancer) +- wezterm + [https://github.com/wez/wezterm](https://github.com/wez/wezterm) + +- aminal + [https://github.com/liamg/aminal](https://github.com/liamg/aminal) + +- iTerm2 (>= 3.0.0) + [https://gitlab.com/gnachman/iterm2](https://gitlab.com/gnachman/iterm2) + +- st-sixel + [https://github.com/galatolofederico/st-sixel](https://github.com/galatolofederico/st-sixel) + ## Install @@ -309,7 +321,7 @@ You can install libsixel via the following package systems. - [FreeBSD ports](http://portsmon.freebsd.org/portoverview.py?category=graphics&portname=libsixel) - [DPorts](https://github.com/DragonFlyBSD/DPorts/tree/master/graphics/libsixel) - [pkgsrc](http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/graphics/libsixel/) -- [Homebrew tap](https://github.com/aki017/homebrew-sixel) +- [Homebrew](https://formulae.brew.sh/formula/libsixel) - [yacp](https://github.com/fd00/yacp/tree/master/libsixel) - [Debian](https://packages.debian.org/search?searchon=names&keywords=libsixel) - [AUR](https://aur.archlinux.org/packages/libsixel-git/) @@ -1044,6 +1056,12 @@ The MIT License (MIT) - [@turenar](https://github.com/turenar/) - [@mame](https://github.com/mame/) - [@hodefoting](https://github.com/hodefoting/) +- [@fCorleone](@https://github.com/fCorleone) +- [@fgeek](https://github.com/fgeek/) +- [@HongxuChen](https://github.com/HongxuChen/) +- [@YourButterfly](https://github.com/YourButterfly/) +- [@nluedtke](https://github.com/nluedtke/) +- [@cool-tomato](https://github.com/cool-tomato/) ## Contributing @@ -1459,3 +1477,36 @@ We are greatly inspired by the quality of ImageMagick and added some resampling - [gr framework](http://gr-framework.org/) +- [o2sh/onefetch](https://github.com/o2sh/onefetch) + +- [lesnitsky/sixel-decoder](https://github.com/lesnitsky/sixel-decoder) + +- [unhappychoice/irasutoya-cli](https://github.com/unhappychoice/irasutoya-cli) + +- [ushitora-anqou/tinysixel](https://github.com/ushitora-anqou/tinysixel) + +- [adzierzanowski/timg](https://github.com/adzierzanowski/timg) + +- [SAT1226/Minase](https://github.com/SAT1226/Minase) + +- [danr/neptyne](https://github.com/danr/neptyne) + +- [klamonte/jexer](https://github.com/klamonte/jexer) + +- [ar90n/teimpy](https://github.com/ar90n/teimpy) + +- [fastai](https://github.com/fastai/fastai) + +- [coderobe/crixel](https://github.com/coderobe/crixel) + +- [itchyny/mkrg](https://github.com/itchyny/mkrg) + +- [tshort/SixelTerm.jl](https://github.com/tshort/SixelTerm.jl) + +- [dsanson/termpdf](https://github.com/dsanson/termpdf) + +- [otiai10/amesh](https://github.com/otiai10/amesh) + +- [hpjansson/chafa](https://github.com/hpjansson/chafa) + +- [m-j-w/TerminalGraphics.jl](https://github.com/m-j-w/TerminalGraphics.jl) diff --git a/configure b/configure index 8395ba55..aee2ddb2 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.2. +# Generated by GNU Autoconf 2.69 for sixel 1.8.3. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sixel' PACKAGE_TARNAME='sixel' -PACKAGE_VERSION='1.8.2' -PACKAGE_STRING='sixel 1.8.2' +PACKAGE_VERSION='1.8.3' +PACKAGE_STRING='sixel 1.8.3' 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.2 to adapt to many kinds of systems. +\`configure' configures sixel 1.8.3 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.2:";; + short | recursive ) echo "Configuration of sixel 1.8.3:";; 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.2 +sixel configure 1.8.3 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.2, which was +It was created by sixel $as_me 1.8.3, 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.2' + VERSION='1.8.3' cat >>confdefs.h <<_ACEOF @@ -16373,7 +16373,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.2, which was +This file was extended by sixel $as_me 1.8.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16439,7 +16439,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.2 +sixel config.status 1.8.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index d65546f5..ba80232b 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.60]) LT_PREREQ([2.4]) -AC_INIT([sixel], [1.8.2], [saitoha@me.com]) +AC_INIT([sixel], [1.8.3], [saitoha@me.com]) LS_LT_CURRENT=1 LS_LT_REVISION=6 LS_LT_AGE=0 diff --git a/converters/img2sixel.1 b/converters/img2sixel.1 index 50005868..691fb18f 100644 --- a/converters/img2sixel.1 +++ b/converters/img2sixel.1 @@ -496,6 +496,11 @@ Yusuke Endoh mattn Akinori Hattori Øyvind Kolås +Henri Salo (@fgeek) +hongxu (@HongxuChen) +pwd (@YourButterfly) +Nicholas Luedtke (@nluedtke) +cool-tomato (@cool-tomato) .fi diff --git a/include/sixel.h.in b/include/sixel.h.in index 7ffe90fa..01ef8f40 100644 --- a/include/sixel.h.in +++ b/include/sixel.h.in @@ -60,6 +60,7 @@ typedef int SIXELSTATUS; #define SIXEL_BAD_ALLOCATION (SIXEL_RUNTIME_ERROR | 0x0001) /* malloc() failed */ #define SIXEL_BAD_ARGUMENT (SIXEL_RUNTIME_ERROR | 0x0002) /* bad argument detected */ #define SIXEL_BAD_INPUT (SIXEL_RUNTIME_ERROR | 0x0003) /* bad input detected */ +#define SIXEL_BAD_INTEGER_OVERFLOW (SIXEL_RUNTIME_ERROR | 0x0004) /* integer overflow */ #define SIXEL_NOT_IMPLEMENTED (SIXEL_FEATURE_ERROR | 0x0001) /* feature not implemented */ @@ -366,6 +367,9 @@ typedef int SIXELSTATUS; #define SIXEL_OPTFLAG_VERSION ('V') /* -V, --version: show version and license info */ #define SIXEL_OPTFLAG_HELP ('H') /* -H, --help: show this help */ +#define SIXEL_WIDTH_LIMIT 1000000 +#define SIXEL_HEIGHT_LIMIT 1000000 + #if SIXEL_USE_DEPRECATED_SYMBOLS /* output character size */ enum characterSize { diff --git a/package.json b/package.json index edb3f4b5..a2383287 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "libsixel", - "version": "1.8.2", + "version": "1.8.3", "repo": "saitoha/libsixel", "description": "A lightweight, fast implementation of DEC SIXEL graphics codec", "keywords": ["terminal", "graphics", "image", "sixel"], diff --git a/src/allocator.c b/src/allocator.c index b9b2d02a..bb0c009f 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -147,6 +147,11 @@ sixel_allocator_malloc( assert(allocator); assert(allocator->fn_malloc); + if (n == 0) { + sixel_helper_set_additional_message( + "sixel_allocator_malloc: called with n == 0"); + return NULL; + } return allocator->fn_malloc(n); } diff --git a/src/decoder.c b/src/decoder.c index 63ab4aff..c763e4d3 100644 --- a/src/decoder.c +++ b/src/decoder.c @@ -315,6 +315,11 @@ sixel_decoder_decode( goto end; } + if (sx > SIXEL_WIDTH_LIMIT || sy > SIXEL_HEIGHT_LIMIT) { + status = SIXEL_BAD_INPUT; + goto end; + } + status = sixel_helper_write_image_file(indexed_pixels, sx, sy, palette, SIXEL_PIXELFORMAT_PAL8, decoder->output, diff --git a/src/fromgif.c b/src/fromgif.c index c13b0055..64248333 100644 --- a/src/fromgif.c +++ b/src/fromgif.c @@ -58,6 +58,10 @@ typedef struct unsigned char suffix; } gif_lzw; +enum { + gif_lzw_max_code_size = 12 +}; + typedef struct { int w, h; @@ -65,13 +69,14 @@ typedef struct int flags, bgindex, ratio, transparent, eflags; unsigned char pal[256][3]; unsigned char lpal[256][3]; - gif_lzw codes[4096]; + gif_lzw codes[1 << gif_lzw_max_code_size]; unsigned char *color_table; int parse, step; int lflags; int start_x, start_y; int max_x, max_y; int cur_x, cur_y; + int actual_width, actual_height; int line_size; int loop_count; int delay; @@ -270,7 +275,14 @@ gif_out_code( return; } - g->out[g->cur_x + g->cur_y] = g->codes[code].suffix; + g->out[g->cur_x + g->cur_y * g->line_size] = g->codes[code].suffix; + if (g->cur_x >= g->actual_width) { + g->actual_width = g->cur_x + 1; + } + if (g->cur_y >= g->actual_height) { + g->actual_height = g->cur_y + 1; + } + g->cur_x++; if (g->cur_x >= g->max_x) { @@ -278,7 +290,7 @@ gif_out_code( g->cur_y += g->step; while (g->cur_y >= g->max_y && g->parse > 0) { - g->step = (1 << g->parse) * g->line_size; + g->step = 1 << g->parse; g->cur_y = g->start_y + (g->step >> 1); --g->parse; } @@ -299,7 +311,15 @@ gif_process_raster( signed int codesize, codemask, avail, oldcode, bits, valid_bits, clear; gif_lzw *p; + /* LZW Minimum Code Size */ lzw_cs = gif_get8(s); + if (lzw_cs > gif_lzw_max_code_size) { + sixel_helper_set_additional_message( + "Unsupported GIF (LZW code size)"); + status = SIXEL_RUNTIME_ERROR; + goto end; + } + clear = 1 << lzw_cs; first = 1; codesize = lzw_cs + 1; @@ -353,7 +373,7 @@ gif_process_raster( goto end; } if (oldcode >= 0) { - if (avail < 4096) { + if (avail < (1 << gif_lzw_max_code_size)) { p = &g->codes[avail++]; p->prefix = (signed short) oldcode; p->first = g->codes[oldcode].first; @@ -408,36 +428,51 @@ gif_load_next( for (;;) { switch (gif_get8(s)) { - case 0x2C: /* Image Descriptor */ - x = gif_get16le(s); - y = gif_get16le(s); - w = gif_get16le(s); - h = gif_get16le(s); + case 0x2C: /* Image Separator (1 byte) */ + x = gif_get16le(s); /* Image Left Position (2 bytes)*/ + y = gif_get16le(s); /* Image Top Position (2 bytes) */ + w = gif_get16le(s); /* Image Width (2 bytes) */ + h = gif_get16le(s); /* Image Height (2 bytes) */ if (((x + w) > (g->w)) || ((y + h) > (g->h))) { sixel_helper_set_additional_message( - "corrupt GIF (reason: bad Image Descriptor)."); + "corrupt GIF (reason: bad Image Separator)."); status = SIXEL_RUNTIME_ERROR; goto end; } g->line_size = g->w; g->start_x = x; - g->start_y = y * g->line_size; + g->start_y = y; g->max_x = g->start_x + w; - g->max_y = g->start_y + h * g->line_size; + g->max_y = g->start_y + h; g->cur_x = g->start_x; g->cur_y = g->start_y; - + g->actual_width = g->start_x; + g->actual_height = g->start_y; + + /* Packed Fields (1 byte) + * +-+-+-+--+---+ + * | | | | | | + * +-+-+-+--+---+ + * | | | | | + * | | | | +- Size of Local Color Table (3 bits) + * | | | +- Reserved (2 bits) + * | | +- Sort Flag (1 bit) + * | +- Interlace Flag (1 bit) + * +- Local Color Table Flag (1 bit) + */ g->lflags = gif_get8(s); + /* Interlace Flag */ if (g->lflags & 0x40) { - g->step = 8 * g->line_size; /* first interlaced spacing */ + g->step = 8; /* first interlaced spacing */ g->parse = 3; } else { - g->step = g->line_size; + g->step = 1; g->parse = 0; } + /* Local Color Table Flag */ if (g->lflags & 0x80) { gif_parse_colortable(s, g->lpal, @@ -465,13 +500,13 @@ gif_load_next( } goto end; - case 0x21: /* Comment Extension. */ + case 0x21: /* Comment Extension. */ switch (gif_get8(s)) { - case 0x01: /* Plain Text Extension */ + case 0x01: /* Plain Text Extension */ break; - case 0x21: /* Comment Extension */ + case 0x21: /* Comment Extension */ break; - case 0xF9: /* Graphic Control Extension */ + case 0xF9: /* Graphic Control Extension */ len = gif_get8(s); /* block size */ if (len == 4) { g->eflags = gif_get8(s); @@ -482,8 +517,8 @@ gif_load_next( break; } break; - case 0xFF: /* Application Extension */ - len = gif_get8(s); /* block size */ + case 0xFF: /* Application Extension */ + len = gif_get8(s); /* block size */ if (s->img_buffer + len > s->img_buffer_end) { status = SIXEL_RUNTIME_ERROR; goto end; @@ -516,7 +551,7 @@ gif_load_next( } break; - case 0x3B: /* gif stream termination code */ + case 0x3B: /* gif stream termination code */ g->is_terminated = 1; status = SIXEL_OK; goto end; @@ -604,8 +639,8 @@ load_gif( break; } - frame->width = g.w; - frame->height = g.h; + frame->width = g.actual_width; + frame->height = g.actual_height; status = gif_init_frame(frame, &g, bgcolor, reqcolors, fuse_palette); if (status != SIXEL_OK) { goto end; diff --git a/src/frompnm.c b/src/frompnm.c index 44529db1..86d0c039 100644 --- a/src/frompnm.c +++ b/src/frompnm.c @@ -166,7 +166,7 @@ load_pnm(unsigned char /* in */ *p, height = 0; for (; *s >= '0' && *s <= '9'; ++s) { height = height * 10 + (*s - '0'); - if (width > PNM_MAX_WIDTH) { + if (height > PNM_MAX_HEIGHT) { status = SIXEL_RUNTIME_ERROR; sprintf( message, @@ -193,7 +193,7 @@ load_pnm(unsigned char /* in */ *p, for (; *s >= '0' && *s <= '9'; ++s) { deps = deps * 10 + (*s - '0'); } - if (width > PNM_MAX_WIDTH) { + if (deps > PNM_MAX_DEPTH) { status = SIXEL_RUNTIME_ERROR; sprintf( message, diff --git a/src/fromsixel.c b/src/fromsixel.c index 7d8390a4..e0332ae6 100644 --- a/src/fromsixel.c +++ b/src/fromsixel.c @@ -52,6 +52,7 @@ #include #include /* isdigit */ #include /* memcpy */ +#include #if defined(HAVE_INTTYPES_H) # include @@ -290,7 +291,7 @@ image_buffer_resize( size = (size_t)(width * height); alt_buffer = (unsigned char *)sixel_allocator_malloc(allocator, size); - if (alt_buffer == NULL) { + if (alt_buffer == NULL || size == 0) { /* free source image */ sixel_allocator_free(allocator, image->data); image->data = NULL; @@ -367,6 +368,16 @@ parser_context_init(parser_context_t *context) return status; } +SIXELSTATUS safe_addition_for_params(parser_context_t *context, unsigned char *p){ + 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; + } + context->param = context->param * 10 + x; + return SIXEL_OK; +} /* convert sixel data into indexed pixel bytes and palette data */ SIXELAPI SIXELSTATUS @@ -446,7 +457,10 @@ sixel_decode_raw_impl( if (context->param < 0) { context->param = 0; } - context->param = context->param * 10 + *p - '0'; + status = safe_addition_for_params(context, p); + if (SIXEL_FAILED(status)) { + goto end; + } p++; break; case ';': @@ -572,6 +586,10 @@ sixel_decode_raw_impl( image->ncolors = context->color_index; } + if (context->pos_x < 0 || context->pos_y < 0) { + status = SIXEL_BAD_INPUT; + goto end; + } bits = *p - '?'; if (bits == 0) { @@ -647,7 +665,10 @@ sixel_decode_raw_impl( case '7': case '8': case '9': - context->param = context->param * 10 + *p - '0'; + status = safe_addition_for_params(context, p); + if (SIXEL_FAILED(status)) { + goto end; + } p++; break; case ';': @@ -721,7 +742,10 @@ sixel_decode_raw_impl( case '7': case '8': case '9': - context->param = context->param * 10 + *p - '0'; + status = safe_addition_for_params(context, p); + if (SIXEL_FAILED(status)) { + goto end; + } p++; break; default: @@ -729,6 +753,10 @@ sixel_decode_raw_impl( if (context->repeat_count == 0) { context->repeat_count = 1; } + if (context->repeat_count > 0xffff) { /* check too huge number */ + status = SIXEL_BAD_INPUT; + goto end; + } context->state = PS_DECSIXEL; context->param = 0; context->nparams = 0; @@ -753,7 +781,10 @@ sixel_decode_raw_impl( case '7': case '8': case '9': - context->param = context->param * 10 + *p - '0'; + status = safe_addition_for_params(context, p); + if (SIXEL_FAILED(status)) { + goto end; + } p++; break; case ';': @@ -884,7 +915,10 @@ sixel_decode_raw( } *ncolors = image.ncolors + 1; - *palette = (unsigned char *)sixel_allocator_malloc(allocator, (size_t)(*ncolors * 3)); + int alloc_size = *ncolors; + if (alloc_size < 256) // memory access range should be 0 <= 255 (in write_png_to_file) + alloc_size = 256; + *palette = (unsigned char *)sixel_allocator_malloc(allocator, (size_t)(alloc_size * 3)); if (palette == NULL) { sixel_allocator_free(allocator, image.data); sixel_helper_set_additional_message( diff --git a/src/loader.c b/src/loader.c index cb1e61f8..111daec9 100644 --- a/src/loader.c +++ b/src/loader.c @@ -195,6 +195,12 @@ load_jpeg(unsigned char **result, while (cinfo.output_scanline < cinfo.output_height) { jpeg_read_scanlines(&cinfo, buffer, 1); + if (cinfo.err->num_warnings > 0) { + sixel_helper_set_additional_message( + "jpeg_read_scanlines: error/warining occuered."); + status = SIXEL_BAD_INPUT; + goto end; + } memcpy(*result + (cinfo.output_scanline - 1) * row_stride, buffer[0], row_stride); } @@ -941,10 +947,11 @@ load_with_gdkpixbuf( GdkPixbuf *pixbuf; GdkPixbufAnimation *animation; GdkPixbufLoader *loader = NULL; -#if 1 GdkPixbufAnimationIter *it; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" GTimeVal time_val; -#endif +#pragma GCC diagnostic pop sixel_frame_t *frame = NULL; int stride; unsigned char *p; @@ -963,7 +970,10 @@ load_with_gdkpixbuf( #if (!GLIB_CHECK_VERSION(2, 36, 0)) g_type_init(); #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" g_get_current_time(&time_val); +#pragma GCC diagnostic pop loader = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(loader, pchunk->buffer, pchunk->size, NULL); animation = gdk_pixbuf_loader_get_animation(loader); @@ -1006,7 +1016,10 @@ load_with_gdkpixbuf( goto end; } } else { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" g_get_current_time(&time_val); +#pragma GCC diagnostic pop frame->frame_no = 0; @@ -1014,7 +1027,10 @@ load_with_gdkpixbuf( for (;;) { while (!gdk_pixbuf_animation_iter_on_currently_loading_frame(it)) { frame->delay = gdk_pixbuf_animation_iter_get_delay_time(it); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" g_time_val_add(&time_val, frame->delay * 1000); +#pragma GCC diagnostic pop frame->delay /= 10; pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(it); if (pixbuf == NULL) { diff --git a/src/status.c b/src/status.c index 7ba38be0..2e4d83ea 100644 --- a/src/status.c +++ b/src/status.c @@ -46,6 +46,7 @@ #define SIXEL_MESSAGE_BAD_ALLOCATION ("runtime error: bad allocation error") #define SIXEL_MESSAGE_BAD_ARGUMENT ("runtime error: bad argument detected") #define SIXEL_MESSAGE_BAD_INPUT ("runtime error: bad input detected") +#define SIXEL_MESSAGE_BAD_INTEGER_OVERFLOW ("runtime error: integer overflow") #define SIXEL_MESSAGE_RUNTIME_ERROR ("runtime error") #define SIXEL_MESSAGE_LOGIC_ERROR ("logic error") #define SIXEL_MESSAGE_NOT_IMPLEMENTED ("feature error: not implemented") @@ -68,6 +69,8 @@ sixel_helper_set_additional_message( { size_t len; + if (message == 0) + return; len = strlen(message); memcpy(g_buffer, message, len < sizeof(g_buffer) ? len: sizeof(g_buffer) - 1); g_buffer[sizeof(g_buffer) - 1] = 0; @@ -118,6 +121,9 @@ sixel_helper_format_error( case SIXEL_BAD_INPUT: error_string = SIXEL_MESSAGE_BAD_INPUT; break; + case SIXEL_BAD_INTEGER_OVERFLOW: + error_string = SIXEL_MESSAGE_BAD_INTEGER_OVERFLOW; + break; default: error_string = SIXEL_MESSAGE_RUNTIME_ERROR; break; diff --git a/src/stb_image.h b/src/stb_image.h index 26738094..48c5f2ae 100644 --- a/src/stb_image.h +++ b/src/stb_image.h @@ -845,6 +845,8 @@ static const char *stbi__g_failure_reason; STBIDEF const char *stbi_failure_reason(void) { + if (stbi__g_failure_reason == NULL) + stbi__g_failure_reason = "unknwon error, refer error message before assignment"; return stbi__g_failure_reason; } @@ -2017,6 +2019,7 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__ // first scan for DC coefficient, must be first memset(data,0,64*sizeof(data[0])); // 0 all the ac values now t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t >= 16) return stbi__err("bad huffman code","Corrupt JPEG"); diff = t ? stbi__extend_receive(j, t) : 0; dc = j->img_comp[b].dc_pred + diff; @@ -5566,6 +5569,7 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req // OK, if I need to read a pixel, do it now if ( read_next_pixel ) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","TGA file too short"); // load however much data we did have if ( tga_indexed ) { @@ -5666,6 +5670,7 @@ static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) count = 0; while ((nleft = pixelCount - count) > 0) { + if (stbi__at_eof(s)) return 0; len = stbi__get8(s); if (len == 128) { // No-op. @@ -5780,7 +5785,6 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req // Initialize the data to zero. //memset( out, 0, pixelCount * 4 ); - // Finally, the image data. if (compression) { // RLE as used by .PSD and .TIFF @@ -5835,16 +5839,22 @@ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req } else { if (ri->bits_per_channel == 16) { // output bpc stbi__uint16 *q = ((stbi__uint16 *) out) + channel; - for (i = 0; i < pixelCount; i++, q += 4) + for (i = 0; i < pixelCount; i++, q += 4) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PSD file too short"); *q = (stbi__uint16) stbi__get16be(s); + } } else { stbi_uc *p = out+channel; if (bitdepth == 16) { // input bpc - for (i = 0; i < pixelCount; i++, p += 4) + for (i = 0; i < pixelCount; i++, p += 4) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PSD file too short"); *p = (stbi_uc) (stbi__get16be(s) >> 8); + } } else { - for (i = 0; i < pixelCount; i++, p += 4) + for (i = 0; i < pixelCount; i++, p += 4) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PSD file too short"); *p = stbi__get8(s); + } } } } diff --git a/src/tosixel.c b/src/tosixel.c index 0166dc4f..220940c1 100644 --- a/src/tosixel.c +++ b/src/tosixel.c @@ -21,6 +21,7 @@ #include #include #include +#include #if defined(HAVE_INTTYPES_H) # include @@ -502,6 +503,7 @@ sixel_encode_body( int mx; int len; int pix; + int check_integer_overflow; unsigned char *map = NULL; sixel_node_t *np, *tp, top; int fillable; @@ -557,8 +559,30 @@ sixel_encode_body( fillable = 1; } for (x = 0; x < width; x++) { - pix = pixels[y * width + x]; /* color index */ + if (y > INT_MAX / width) { + /* integer overflow */ + status = SIXEL_BAD_INTEGER_OVERFLOW; + goto end; + } + check_integer_overflow = y * width; + if (check_integer_overflow > INT_MAX - x) { + /* integer overflow */ + 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 */ + status = SIXEL_BAD_INTEGER_OVERFLOW; + goto end; + } + check_integer_overflow = pix * width; + if (check_integer_overflow > INT_MAX - x) { + /* integer overflow */ + status = SIXEL_BAD_INTEGER_OVERFLOW; + goto end; + } map[pix * width + x] |= (1 << i); } else if (!palstate) {