Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

two bug in jpeg encoding #87

Closed
kdsjZh opened this issue Jun 26, 2023 · 2 comments
Closed

two bug in jpeg encoding #87

kdsjZh opened this issue Jun 26, 2023 · 2 comments

Comments

@kdsjZh
Copy link

kdsjZh commented Jun 26, 2023

Hello, I was playing with my new fuzzer and found two bugs in jpeg's encoding module.

Environment

Ubuntu 20.04, gcc 9.4.0, libjpeg latest commit db33a6e

Compile with gcc and AddressSanitizer.

run the program with ./jpeg -p @@ /dev/null

BUG0

jpeg Copyright (C) 2012-2018 Thomas Richter, University of Stuttgart
and Accusoft

For license conditions, see README.license for details.

=================================================================
==666872==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x62500000f408 at pc 0x559ad43fba61 bp 0x7ffc1d504e10 sp 0x7ffc1d504e00
READ of size 4 at 0x62500000f408 thread T0
    #0 0x559ad43fba60 in YCbCrTrafo<unsigned short, 1, (unsigned char)1, 1, 0>::RGB2YCbCr(RectAngle<int> const&, ImageBitMap const* const*, int**) (/fuzz/libjpeg/crash/jpeg.asan+0x1d4a60)
    #1 0x559ad459610b in LineBitmapRequester::EncodeRegion(RectAngle<int> const&) /benchmark/libjpeg/control/linebitmaprequester.cpp:404
    #2 0x559ad42b97dd in Image::EncodeRegion(BitMapHook*, RectangleRequest const*) /benchmark/libjpeg/codestream/image.cpp:1159
    #3 0x559ad42a20d0 in JPEG::InternalProvideImage(JPG_TagItem*) /benchmark/libjpeg/interface/jpeg.cpp:813
    #4 0x559ad42a157b in JPEG::ProvideImage(JPG_TagItem*) /benchmark/libjpeg/interface/jpeg.cpp:732
    #5 0x559ad4281d5e in EncodeC(char const*, char const*, char const*, char const*, int, int, int, int, int, int, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, unsigned char, bool, bool, unsigned int, double, int, bool, bool, bool, bool, bool, bool, bool, bool, bool, int, int, int, bool, bool, bool, int, bool, char const*, char const*, char const*, int, int, int, int, bool, int, int, int, int, int, int, int, bool, bool, bool, bool, bool, bool, char const*, char const*, char const*, char const*) /benchmark/libjpeg/cmd/encodec.cpp:693
    #6 0x559ad4271517 in main /benchmark/libjpeg/cmd/main.cpp:760
    #7 0x7f910caca082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
    #8 0x559ad426d9ad in _start (/fuzz/libjpeg/crash/jpeg.asan+0x469ad)

Address 0x62500000f408 is a wild pointer.
SUMMARY: AddressSanitizer: heap-buffer-overflow (/fuzz/libjpeg/crash/jpeg.asan+0x1d4a60) in YCbCrTrafo<unsigned short, 1, (unsigned char)1, 1, 0>::RGB2YCbCr(RectAngle<int> const&, ImageBitMap const* const*, int**)
Shadow bytes around the buggy address:
  0x0c4a7fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9e50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9e60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9e70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c4a7fff9e80: fa[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9e90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9ea0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9eb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9ec0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c4a7fff9ed0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==666872==ABORTING

poc0.zip

BUG1

jpeg Copyright (C) 2012-2018 Thomas Richter, University of Stuttgart
and Accusoft

For license conditions, see README.license for details.

jpeg.asan: bitmaphook.cpp:111: JPG_LONG BitmapHook(JPG_Hook*, JPG_TagItem*): Assertion `maxy - miny < bmm->bmm_ulHeight' failed.
Aborted

The StackTrace is below:

#0  BitMapHook::BitMapHook (this=0x0, tags=0x0) at bitmaphook.cpp:61
#1  0x0000564ba8fbf899 in JPEG::InternalProvideImage (this=0x61b000000098, tags=0x7fff2ffd9430) at jpeg.cpp:776
#2  0x0000564ba8fbf57c in JPEG::ProvideImage (this=0x61b000000098, tags=0x7fff2ffd9430) at jpeg.cpp:732
#3  0x0000564ba8f9fd5f in EncodeC (source=0x7fff3009b88d "crashes/poc.assert.BitmapHook", ldrsource=0x0, target=0x7fff3009b8ab "/dev/null", ltable=0x0,
    quality=-1, hdrquality=-1, tabletype=0, residualtt=0, maxerror=0, colortrafo=1, baseline=false, lossless=true, progressive=false, residual=false,
    optimize=false, accoding=false, rsequential=false, rprogressive=false, raccoding=false, qscan=false, levels=0 '\000', pyramidal=false, writednl=false,
    restart=0, gamma=0, lsmode=-1, noiseshaping=false, serms=false, losslessdct=false, openloop=false, deadzone=false, lagrangian=false, dering=false,
    xyz=false, cxyz=false, hiddenbits=0, riddenbits=0, resprec=8, separate=false, median=true, noclamp=true, smooth=0, dctbypass=false, sub=0x0,
    ressub=0x0, alpha=0x0, alphamode=1, matte_r=0, matte_g=0, matte_b=0, alpharesiduals=false, alphaquality=70, alphahdrquality=0, alphatt=0,
    residualalphatt=0, ahiddenbits=0, ariddenbits=0, aresprec=8, aopenloop=false, adeadzone=false, alagrangian=false, adering=false, aserms=false,
    abypass=false, quantsteps=0x0, residualquantsteps=0x0, alphasteps=0x0, residualalphasteps=0x0) at encodec.cpp:693
#4  0x0000564ba8f8f518 in main (argc=3, argv=0x7fff3009a6c0) at main.cpp:760

poc1.zip

@kdsjZh kdsjZh changed the title two bug in jpeg decoding two bug in jpeg encoding Jun 26, 2023
@thorfdbg
Copy link
Owner

thorfdbg commented Jul 7, 2023

Yes, thank you. Those two issues are fixed - on this particular input. One problem was that the input bitmap hook could not report an error if requesting or releasing a bitmap did not work. This has been fixed and the code was extended to collect such error codes to the caller.

However, please note that the example code in the "cmd" directory is not particular robust, and is not attempted to constitute a robust implementation. If the code is required to operate in a hostile environment, the bitmap hook implementation needs to sanetize its input as the library encoder (not the decoder!) operates under the assumption that input data is valid (i.e. "garbadge-in garbadge-out"). If that cannot be assumed, the bitmap hook is required to perform such validation, and generate an error (or fix the data).

@thorfdbg thorfdbg closed this as completed Jul 7, 2023
@samueloph
Copy link

samueloph commented Jul 14, 2023

Two CVEs were assigned to this bugreport, one for each bug:

CVE-2023-37836 and CVE-2023-37837

Note: I didn't have any involvement in this assignment, I'm just posting here for reference.

This seems to be the fixing commit:
9e0cea2

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

No branches or pull requests

3 participants