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

Fix Attempt to free an uninitialized memory pointer in vorbis_deinit (GHSL-2023-169/CVE-2023-45679) #1557

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

JarLob
Copy link

@JarLob JarLob commented Oct 19, 2023

A crafted file may trigger memory allocation failure in start_decoder at [1]. In that case the function returns early [2], but some of the pointers in f->comment_list are left initialized [3].

   f->comment_list_length = get32_packet(f);
   f->comment_list = NULL;
   if (f->comment_list_length > 0)
   {
      f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); // [3]
      if (f->comment_list == NULL)                  return error(f, VORBIS_outofmem);
   }

   for(i=0; i < f->comment_list_length; ++i) {
      len = get32_packet(f);
      f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1)); // [1] OOM
      if (f->comment_list[i] == NULL)               return error(f, VORBIS_outofmem); // [2]

      for(j=0; j < len; ++j) {
         f->comment_list[i][j] = get8_packet(f);
      }
      f->comment_list[i][len] = (char)'\0';
   }

Later setup_free is called on these pointers in vorbis_deinit [4].

static void vorbis_deinit(stb_vorbis *p)
{
   int i,j;

   setup_free(p, p->vendor);
   for (i=0; i < p->comment_list_length; ++i) {
      setup_free(p, p->comment_list[i]); // [4]
   }

Impact

This issue may lead to code execution.

Resources

To reproduce the issue:

  1. Make ASAN build of the following program:
#include "../stb_vorbis.c"
#include <stdint.h>

int main(int argc, char* argv[])
{
    const uint8_t data[] = {0x4f,0x67,0x67,0x53,0x00,0x7a,0x18,0xfe,0xa9,0x00,0x53,
                            0x00,0xe3,0xb5,0x21,0x68,0x00,0x00,0x00,0x00,0x00,0x00,
                            0x6b,0x0e,0xa0,0x75,0x01,0x1e,0x01,0x76,0x6f,0x72,0x62,
                            0x69,0x73,0x00,0x00,0x00,0x00,0x01,0xfb,0x07,0xae,0x69,
                            0x73,0x00,0x00,0x00,0x00,0x2e,0x09,0x3c,0xff,0x30,0x00,
                            0x01,0xa9,0xf9,0x4f,0x67,0x67,0x53,0x00,0x00,0x00,0x7e,
                            0x79,0x6f,0x42,0x0c,0xc5,0x97,0x21,0x68,0x00,0x00,0x01,
                            0x00,0x00,0x00,0x6f,0x11,0x00,0x00,0x00,0x03,0x76,0x6f,
                            0x72,0x62,0x69,0x73,0x00,0x00,0x00,0x00,0x2e};
    size_t size = sizeof(data);

    int chan, samplerate;
    short *output;
    int samples = stb_vorbis_decode_memory(data, size, &chan, &samplerate, &output);
    if (samples >= 0)
        free(output);
    return 0;
}
  1. Run the program with an instruction that allocator may fail (otherwise ASAN will quit early with AddressSanitizer: requested allocation size ... exceeds maximum supported size): ASAN_OPTIONS=allocator_may_return_null=1 <program name> to hit the error.
AddressSanitizer:DEADLYSIGNAL
=================================================================
==217447==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x00000041f6d4 bp 0x000000000000 sp 0x7ffd3e146c60 T0)
==217447==The signal is caused by a READ memory access.
    #0 0x41f6d4 in atomic_compare_exchange_strong<__sanitizer::atomic_uint8_t> /src/llvm-project/compiler-rt/lib/asan/../sanitizer_common/sanitizer_atomic_clang.h:81:10
    #1 0x41f6d4 in AtomicallySetQuarantineFlagIfAllocated /src/llvm-project/compiler-rt/lib/asan/asan_allocator.cpp:610:10
    #2 0x41f6d4 in __asan::Allocator::Deallocate(void*, unsigned long, unsigned long, __sanitizer::BufferedStackTrace*, __asan::AllocType) /src/llvm-project/compiler-rt/lib/asan/asan_allocator.cpp:685:10
    #3 0x49e5d5 in free /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:53:3
    #4 0x4dcedb in setup_free(stb_vorbis*, void*) tests/../stb_vorbis.c:966:4
    #5 0x4dbe57 in vorbis_deinit(stb_vorbis*) tests/../stb_vorbis.c:4214:7
    #6 0x4f9638 in stb_vorbis_open_memory tests/../stb_vorbis.c:5122:4
    #7 0x4fbfb1 in stb_vorbis_decode_memory tests/../stb_vorbis.c:5390:20

@sezero
Copy link

sezero commented Dec 10, 2023

This #1557 and next #1558 must be combined into the following, and #1558 must be discarded.

diff --git a/stb_vorbis.c b/stb_vorbis.c
index 3e5c250..3dbfb55 100644
--- a/stb_vorbis.c
+++ b/stb_vorbis.c
@@ -3662,7 +3662,11 @@ static int start_decoder(vorb *f)
    if (f->comment_list_length > 0)
    {
       f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length));
-      if (f->comment_list == NULL)                  return error(f, VORBIS_outofmem);
+      if (f->comment_list == NULL) {
+         f->comment_list_length = 0;
+         return error(f, VORBIS_outofmem);
+      }
+      memset(f->comment_list, 0, sizeof(char*) * f->comment_list_length);
    }
 
    for(i=0; i < f->comment_list_length; ++i) {

sezero added a commit to sezero/SDL_mixer that referenced this pull request Dec 11, 2023
Based on the patches by Jaroslav Lobačevski (@JarLob) submitted
to mainstream at: nothings/stb#1557 and
nothings/stb#1558

GHSL-2023-169/CVE-2023-45679: Attempt to free an uninitialized memory pointer in vorbis_deinit()
GHSL-2023-170/CVE-2023-45680: Null pointer dereference in vorbis_deinit()
icculus pushed a commit to libsdl-org/SDL_mixer that referenced this pull request Dec 11, 2023
Based on the patches by Jaroslav Lobačevski (@JarLob) submitted
to mainstream at: nothings/stb#1557 and
nothings/stb#1558

GHSL-2023-169/CVE-2023-45679: Attempt to free an uninitialized memory pointer in vorbis_deinit()
GHSL-2023-170/CVE-2023-45680: Null pointer dereference in vorbis_deinit()
sezero added a commit to libsdl-org/SDL_mixer that referenced this pull request Dec 11, 2023
Based on the patches by Jaroslav Lobačevski (@JarLob) submitted
to mainstream at: nothings/stb#1557 and
nothings/stb#1558

GHSL-2023-169/CVE-2023-45679: Attempt to free an uninitialized memory pointer in vorbis_deinit()
GHSL-2023-170/CVE-2023-45680: Null pointer dereference in vorbis_deinit()

(cherry picked from commit 4361f57)
sezero added a commit to icculus/SDL_sound that referenced this pull request Dec 11, 2023
Based on the patches by Jaroslav Lobačevski (@JarLob) submitted
to mainstream at: nothings/stb#1557 and
nothings/stb#1558

GHSL-2023-169/CVE-2023-45679: Attempt to free an uninitialized memory pointer in vorbis_deinit()
GHSL-2023-170/CVE-2023-45680: Null pointer dereference in vorbis_deinit()
sezero added a commit to sezero/libxmp that referenced this pull request Dec 11, 2023
Based on the patches by Jaroslav Lobačevski (@JarLob) submitted
to mainstream at: nothings/stb#1557 and
nothings/stb#1558

GHSL-2023-169/CVE-2023-45679: Attempt to free an uninitialized memory pointer in vorbis_deinit()
GHSL-2023-170/CVE-2023-45680: Null pointer dereference in vorbis_deinit()
sezero added a commit to sezero/stb that referenced this pull request Dec 12, 2023
Based on the patches by Jaroslav Lobačevski (@JarLob) submitted
to mainstream at: nothings#1557 and
nothings#1558

GHSL-2023-169/CVE-2023-45679: Attempt to free an uninitialized memory pointer in vorbis_deinit()
GHSL-2023-170/CVE-2023-45680: Null pointer dereference in vorbis_deinit()
NBickford-NV added a commit to NBickford-NV/stb that referenced this pull request Feb 17, 2024
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

Successfully merging this pull request may close these issues.

None yet

2 participants