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

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/libgd/libgd/issues/697
## Description:
Issue: libgd/libgd#697
Title: Read out of bound in TGA files
State: closed
Created by: meweez
Created at: 2021-04-30 18:12:52+00:00

Issue Body:
hello,
[this issue](https://github.com/libgd/libgd/issues/247#issue-163166532) is showing a read out of bound for a corrupted TGA [test.txt](https://github.com/libgd/libgd/files/6407187/test.txt) which is patched by adding some checks for ` gdGetBuf`.

although the patch prevents occurring this vulnerability I saw that this function (` gdGetBuf`) is used in `read_header_tga` too which there is no check for its return value again.

I changed the header of the file which was used for the previous CVE-2016-6132. In fact, I changed the first byte to `ff` which is assigned to `tga->identsize`. 
[file(it is a tga, not a really a txt) ](https://github.com/libgd/libgd/files/6407191/test.txt)


```
...
tga->identsize = header[0];
...
gdGetBuf(tga->ident, tga->identsize, ctx);
...
```

when I run the test with this input file ASAN shows this:
```
AddressSanitizer:DEADLYSIGNAL
=================================================================
==12378==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f685ae4a7a0 bp 0x7fff6bb8b740 sp 0x7fff6bb8b720 T0)
==12378==The signal is caused by a READ memory access.
==12378==Hint: address points to the zero page.
    #0 0x7f685ae4a79f in gdImageDestroy /tmp/libgd/src/gd.c:390
    #1 0x55c05b670432 in main /tmp/libgd/tests/tga/bug00084.c:11
    #2 0x7f685aa3709a in __libc_start_main ../csu/libc-start.c:308
    #3 0x55c05b670339 in _start (/tmp/libgd/build/Bin/test_tga_bug00084+0x2339)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /tmp/libgd/src/gd.c:390 in gdImageDestroy
==12378==ABORTING
```

Is it showing another vulnerability?




Comments:
Comment by meweez on 2021-05-31 21:16:24+00:00:
any comment?

---

Comment by cmb69 on 2021-05-31 21:27:54+00:00:
There might be a bug there, but who needs to read TGAs in … checks calendar … 2021?

---

Comment by pierrejoye on 2021-07-02 07:41:09+00:00:
@me22bee could you upload the full test case or do you use only bug00084.c? 

---

Comment by meweez on 2021-07-02 07:47:51+00:00:
> do you use only bug00084.c?

yes.

---

Comment by pierrejoye on 2021-07-19 04:07:20+00:00:
@me22bee could you attach the patched test file? Should be an easy fix. TGA is still used, indeed not for web but our targets go further than web devs :)

---

Comment by meweez on 2021-07-19 05:58:27+00:00:
> could you attach the patched test file?

I have sent a pull request and also attached the patch file here.
[0001-fix-read-out-of-bands-in-reading-tga-header-file.patch.txt](https://github.com/libgd/libgd/files/6838308/0001-fix-read-out-of-bands-in-reading-tga-header-file.patch.txt)


---

Comment by pierrejoye on 2021-07-19 06:29:25+00:00:
Thank you @me22bee  :)

---

Comment by meweez on 2021-07-19 07:03:02+00:00:
your welcome,
Don't you assign a CVE number to it?
@pierrejoye 

---

Comment by pierrejoye on 2021-07-19 07:13:16+00:00:
let me check with the ***@***.***, we have access :)

On Mon, Jul 19, 2021, 2:03 PM me22bee ***@***.***> wrote:

> your welcome,
> Don't you assign a CVE number to it?
> @pierrejoye <https://github.com/pierrejoye>
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/libgd/libgd/issues/697#issuecomment-882294446>, or
> unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AACE6KCKWJFRWGQSTNHENVTTYPE3DANCNFSM435BOBUQ>
> .
>


---

Comment by meweez on 2021-07-25 04:18:37+00:00:
> let me check with

any update?
@pierrejoye 

---

Comment by carnil on 2021-08-05 08:27:33+00:00:
CVE-2021-38115 seems to have been assigned for this issue.

---

Comment by LearnerOrLearnerr on 2021-09-03 02:23:12+00:00:
Will a release be provided with this security fix?

---

Comment by oerdnj on 2022-07-06 14:28:53+00:00:
> Will a release be provided with this security fix?

FTR the fix has been released in 2.3.3

---

Comment by cmb69 on 2024-09-23 22:10:36+00:00:
For the record: this was not a security issue. The OP run bug00084.c against a modified bug00084.tga, which triggered a segfault. However, this was not due to any issues with reading the TGA, but the badly written bug00084.c, which has been [fixed in the meantime](https://github.com/libgd/libgd/commit/167ea1f4f0003f3e9f7ca1e586189e99cf33d47f#diff-14a20f0399b66f7abcafda3ecd8d7849bf587e7bf564c63d560ee3964177bf61); prior to that commit, bug00084.c did not check whether `gdImageCreateFromTga()` succeeded, but called `gdImageDestroy()` unconditionally. So if reading of the TGA file failed, it called `gdImageDestroy(NULL)` which results in the reported segfault.

Attachments:
https://github.com/libgd/libgd/issues/247#issue-163166532) is showing a read out of bound for a corrupted TGA [test.txt](https://github.com/libgd/libgd/files/6407187/test.txt
https://github.com/libgd/libgd/files/6838308/0001-fix-read-out-of-bands-in-reading-tga-header-file.patch.txt
https://github.com/libgd/libgd/files/6407191/test.txt

Commit References:
167ea1f4f0003f3e9f7ca1e586189e99cf33d47f
14a20f0399b66f7abcafda3ecd8d7849bf587e7b

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 2e40f55bfb460fc9d8cbcd290a0c9eb908d5af7e
WORKDIR $SRC/libgd
COPY build.sh $SRC/

Additional files:
filename: gd_image_string_fuzzer.cc
content: // Copyright 2020 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 <fuzzer/FuzzedDataProvider.h>

#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <string>

#include "gd.h"
#include "gdfontg.h"
#include "gdfontl.h"
#include "gdfontmb.h"
#include "gdfonts.h"
#include "gdfontt.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    FuzzedDataProvider stream(data, size);
    const uint8_t slate_width = stream.ConsumeIntegral<uint8_t>();
    const uint8_t slate_height = stream.ConsumeIntegral<uint8_t>();
    gdImagePtr slate_image = gdImageCreateTrueColor(slate_width, slate_height);
    if (slate_image == nullptr) {
      return 0;
    }

    const int x_position = stream.ConsumeIntegral<int>();
    const int y_position = stream.ConsumeIntegral<int>();
    const int text_color = stream.ConsumeIntegral<int>();
    const gdFontPtr font_ptr = stream.PickValueInArray(
        {gdFontGetGiant(), gdFontGetLarge(), gdFontGetMediumBold(),
        gdFontGetSmall(), gdFontGetTiny()});
    const std::string text = stream.ConsumeRemainingBytesAsString();

    gdImageString(slate_image, font_ptr, x_position, y_position,
                  reinterpret_cast<uint8_t*>(const_cast<char*>(text.c_str())),
                  text_color);
    gdImageDestroy(slate_image);
    return 0;
}

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;
}