Project: libgd (libgd/libgd), language: c++
Vulnerability instance: libgd.cve-2016-6905
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/libgd/libgd/issues/248
## Description:
Issue: libgd/libgd#248
Title: Out-Of-Bounds Read in function read_image_tga of gd_tga.c (CVE-2016-6905)
State: closed
Created by: trylab
Created at: 2016-07-05 04:45:01+00:00
Labels: bug

Issue Body:
Hi, I'd like to report a OOB read issue to you. This issue can be triggered when parsing a specially crafted tga image. You can compile `libgd/tests/tga/bug00084.c` with AddressSanitizer to reproduce this issue.

```
==2755==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb5503f9c at pc 0x081689da bp 0xbf86d738 sp 0xbf86d730
READ of size 1 at 0xb5503f9c thread T0
    #0 0x81689d9 in read_image_tga /tmp/repo/libgd/src/gd_tga.c:293:37
    #1 0x8165b32 in gdImageCreateFromTgaCtx /tmp/repo/libgd/src/gd_tga.c:74:6
    #2 0x8165986 in gdImageCreateFromTga /tmp/repo/libgd/src/gd_tga.c:25:10
    #3 0x81322a1 in main /tmp/repo/libgd/tests/tga/bug00084.c:10:10
    #4 0xb745daf2 in __libc_start_main /build/eglibc-X4bnBz/eglibc-2.19/csu/libc-start.c:287
    #5 0x8078b1b in _start (/tmp/repo/libgd/tests/tga/bug00084+0x8078b1b)

0xb5503f9c is located 0 bytes to the right of 796-byte region [0xb5503c80,0xb5503f9c)
allocated by thread T0 here:
    #0 0x81107a9 in malloc (/tmp/repo/libgd/tests/tga/bug00084+0x81107a9)
    #1 0x8167b77 in read_image_tga /tmp/repo/libgd/src/gd_tga.c:254:37

SUMMARY: AddressSanitizer: heap-buffer-overflow /tmp/repo/libgd/src/gd_tga.c:293 read_image_tga
Shadow bytes around the buggy address:
  0x36aa07a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x36aa07b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x36aa07c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x36aa07d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x36aa07e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x36aa07f0: 00 00 00[04]fa fa fa fa fa fa fa fa fa fa fa fa
  0x36aa0800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36aa0810: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36aa0820: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36aa0830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x36aa0840: 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
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  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
==2755==ABORTING
```

Credit to **Ke Liu of Tencent's Xuanwu LAB**.
Thanks.



Comments:
Comment by trylab on 2016-07-05 04:47:42+00:00:
Please remove the `.txt` extension.
[poc.tga.txt](https://github.com/libgd/libgd/files/347100/poc.tga.txt)


---

Comment by cmb69 on 2016-07-05 10:06:20+00:00:
That might be a duplicate of #247. I'll have a look at it.


---

Comment by oerdnj on 2016-07-12 11:35:52+00:00:
@vapier Tested POC and it's not duplicate.


---

Comment by cmb69 on 2016-07-12 11:56:25+00:00:
@oerdnj I was able to reproduce with valgrind. The file appears to be corrupt wrt. to the RLE.


---

Comment by oerdnj on 2016-07-12 12:02:02+00:00:
@cmb69 I think I have a fix, just a moment to test it.


---

Comment by oerdnj on 2016-07-12 12:05:25+00:00:
The decoding ends with buffer overflow here:

```
3: image_block_size = 796
2: bitmap_caret = 796
1: buffer_caret = 798
```


---

Comment by pierrejoye on 2016-07-13 01:54:46+00:00:
It would be interesting to have the QuickFuzz test flow in a github repo so we can run it from time to time to valid any code changes we make before a release :)


---

Comment by trylab on 2016-08-24 11:48:58+00:00:
According to http://seclists.org/oss-sec/2016/q3/363 , CVE-2016-6905 has been assigned to this issue.


Attachments:
https://github.com/libgd/libgd/files/347100/poc.tga.txt

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
./bootstrap.sh
./configure --prefix="$WORK" --disable-shared
make -j$(nproc) install

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool pkg-config libz-dev
RUN apt-get install -y make autoconf automake libtool pkg-config libz-dev
RUN git clone https://github.com/libgd/libgd libgd
RUN git -C libgd checkout 2ea5232bfd021f85933385a1ad5a88e114fdcf80
WORKDIR $SRC/libgd
COPY build.sh $SRC/

Additional files:
filename: parser_target.cc
content: // Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/////////////////////////////////////////////////////////////////////////////

#include <stdint.h>
#include "gd.h"

#define PASTE(x) gdImageCreateFrom ## x ## Ptr
#define CREATE_IMAGE(FORMAT) PASTE(FORMAT)

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
    gdImagePtr im = CREATE_IMAGE(FUZZ_GD_FORMAT)(Size, (void*) Data);
    if (im) gdImageDestroy(im);
    return 0;
}