Project: matio (tbeu/matio), language: c++
Vulnerability instance: matio.cve-2022-1515
Sanitizer: address

================= Bug Report (1/2) ==================
## Source: GitHub Issue
## URL: https://github.com/tbeu/matio/issues/186
## Description:
Issue: tbeu/matio#186
Title: Memory leaks in Mat_VarReadNextInfo5
State: closed
Created by: andreafioraldi
Created at: 2022-02-17 16:21:15+00:00
Labels: bug

Issue Body:
Hi,
this is an issue found by fuzzing the current master branch, use the OSS-Fuzz harness compiled with ASan and UBSan to reproduce.

The memory leak is in Mat_VarReadNextInfo5, the reported sanitizer error is the following:

```
INFO: Seed: 117854221
INFO: Loaded 1 modules   (269217 inline 8-bit counters): 269217 [0x1c496a0, 0x1c8b241), 
INFO: Loaded 1 PC tables (269217 PCs): 269217 [0x1c8b248,0x20a6c58), 
/out/matio_fuzzer: Running 1 inputs 1 time(s) each.
Running: crashes/matio_matio_fuzzer/id:001628,sig:06,src:007945,time:21810082,op:havoc,rep:2,trial:1496358

=================================================================
==1325517==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 320 byte(s) in 4 object(s) allocated from:
    #0 0x49828d in malloc (/out/matio_fuzzer+0x49828d)
    #1 0x502f4b in Mat_VarCalloc (/out/matio_fuzzer+0x502f4b)
    #2 0x616231 in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x616231)
    #3 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #4 0x6265c8 in ReadNextFunctionHandle (/out/matio_fuzzer+0x6265c8)
    #5 0x6170ef in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6170ef)
    #6 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #7 0x5028a7 in Mat_GetDir (/out/matio_fuzzer+0x5028a7)
    #8 0x4ca408 in MatioRead(char const*) (/out/matio_fuzzer+0x4ca408)
    #9 0x4ca5b1 in LLVMFuzzerTestOneInput (/out/matio_fuzzer+0x4ca5b1)
    #10 0x4dfd99 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/out/matio_fuzzer+0x4dfd99)

Direct leak of 320 byte(s) in 4 object(s) allocated from:
    #0 0x49828d in malloc (/out/matio_fuzzer+0x49828d)
    #1 0x502f4b in Mat_VarCalloc (/out/matio_fuzzer+0x502f4b)
    #2 0x616231 in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x616231)
    #3 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #4 0x6265c8 in ReadNextFunctionHandle (/out/matio_fuzzer+0x6265c8)
    #5 0x6170ef in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6170ef)
    #6 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #7 0x4ca452 in MatioRead(char const*) (/out/matio_fuzzer+0x4ca452)
    #8 0x4ca5b1 in LLVMFuzzerTestOneInput (/out/matio_fuzzer+0x4ca5b1)
    #9 0x4dfd99 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/out/matio_fuzzer+0x4dfd99)

Indirect leak of 256 byte(s) in 4 object(s) allocated from:
    #0 0x49828d in malloc (/out/matio_fuzzer+0x49828d)
    #1 0x502f83 in Mat_VarCalloc (/out/matio_fuzzer+0x502f83)
    #2 0x616231 in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x616231)
    #3 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #4 0x6265c8 in ReadNextFunctionHandle (/out/matio_fuzzer+0x6265c8)
    #5 0x6170ef in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6170ef)
    #6 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #7 0x4ca452 in MatioRead(char const*) (/out/matio_fuzzer+0x4ca452)
    #8 0x4ca5b1 in LLVMFuzzerTestOneInput (/out/matio_fuzzer+0x4ca5b1)
    #9 0x4dfd99 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/out/matio_fuzzer+0x4dfd99)

Indirect leak of 256 byte(s) in 4 object(s) allocated from:
    #0 0x49828d in malloc (/out/matio_fuzzer+0x49828d)
    #1 0x502f83 in Mat_VarCalloc (/out/matio_fuzzer+0x502f83)
    #2 0x616231 in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x616231)
    #3 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #4 0x6265c8 in ReadNextFunctionHandle (/out/matio_fuzzer+0x6265c8)
    #5 0x6170ef in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6170ef)
    #6 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #7 0x5028a7 in Mat_GetDir (/out/matio_fuzzer+0x5028a7)
    #8 0x4ca408 in MatioRead(char const*) (/out/matio_fuzzer+0x4ca408)
    #9 0x4ca5b1 in LLVMFuzzerTestOneInput (/out/matio_fuzzer+0x4ca5b1)
    #10 0x4dfd99 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/out/matio_fuzzer+0x4dfd99)

Indirect leak of 48 byte(s) in 3 object(s) allocated from:
    #0 0x49828d in malloc (/out/matio_fuzzer+0x49828d)
    #1 0x6259a1 in ReadRankDims (/out/matio_fuzzer+0x6259a1)
    #2 0x6165b0 in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6165b0)
    #3 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #4 0x6265c8 in ReadNextFunctionHandle (/out/matio_fuzzer+0x6265c8)
    #5 0x6170ef in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6170ef)
    #6 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #7 0x4ca452 in MatioRead(char const*) (/out/matio_fuzzer+0x4ca452)
    #8 0x4ca5b1 in LLVMFuzzerTestOneInput (/out/matio_fuzzer+0x4ca5b1)
    #9 0x4dfd99 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/out/matio_fuzzer+0x4dfd99)

Indirect leak of 48 byte(s) in 3 object(s) allocated from:
    #0 0x49828d in malloc (/out/matio_fuzzer+0x49828d)
    #1 0x6259a1 in ReadRankDims (/out/matio_fuzzer+0x6259a1)
    #2 0x6165b0 in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6165b0)
    #3 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #4 0x6265c8 in ReadNextFunctionHandle (/out/matio_fuzzer+0x6265c8)
    #5 0x6170ef in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6170ef)
    #6 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #7 0x5028a7 in Mat_GetDir (/out/matio_fuzzer+0x5028a7)
    #8 0x4ca408 in MatioRead(char const*) (/out/matio_fuzzer+0x4ca408)
    #9 0x4ca5b1 in LLVMFuzzerTestOneInput (/out/matio_fuzzer+0x4ca5b1)
    #10 0x4dfd99 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/out/matio_fuzzer+0x4dfd99)

Indirect leak of 3 byte(s) in 3 object(s) allocated from:
    #0 0x49828d in malloc (/out/matio_fuzzer+0x49828d)
    #1 0x616c0b in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x616c0b)
    #2 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #3 0x6265c8 in ReadNextFunctionHandle (/out/matio_fuzzer+0x6265c8)
    #4 0x6170ef in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6170ef)
    #5 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #6 0x4ca452 in MatioRead(char const*) (/out/matio_fuzzer+0x4ca452)
    #7 0x4ca5b1 in LLVMFuzzerTestOneInput (/out/matio_fuzzer+0x4ca5b1)
    #8 0x4dfd99 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/out/matio_fuzzer+0x4dfd99)

Indirect leak of 3 byte(s) in 3 object(s) allocated from:
    #0 0x49828d in malloc (/out/matio_fuzzer+0x49828d)
    #1 0x616c0b in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x616c0b)
    #2 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #3 0x6265c8 in ReadNextFunctionHandle (/out/matio_fuzzer+0x6265c8)
    #4 0x6170ef in Mat_VarReadNextInfo5 (/out/matio_fuzzer+0x6170ef)
    #5 0x502e89 in Mat_VarReadNextInfo (/out/matio_fuzzer+0x502e89)
    #6 0x5028a7 in Mat_GetDir (/out/matio_fuzzer+0x5028a7)
    #7 0x4ca408 in MatioRead(char const*) (/out/matio_fuzzer+0x4ca408)
    #8 0x4ca5b1 in LLVMFuzzerTestOneInput (/out/matio_fuzzer+0x4ca5b1)
    #9 0x4dfd99 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/out/matio_fuzzer+0x4dfd99)

SUMMARY: AddressSanitizer: 1254 byte(s) leaked in 28 allocation(s).

INFO: a leak has been found in the initial corpus.

INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.

```

I attach a testcase that trigger the bug in a tar.gz.

[id:001628,sig:06,src:007945,time:21810082,op:havoc,rep:2,trial:1496358.tar.gz](https://github.com/tbeu/matio/files/8090326/id.001628.sig.06.src.007945.time.21810082.op.havoc.rep.2.trial.1496358.tar.gz)



Comments:
Comment by tbeu on 2022-02-22 20:06:08+00:00:
Thanks for reporting. Fixed by b53b62b.

---

Comment by guitos on 2022-04-28 17:03:13+00:00:
The CVE-2022-1515 has been assigned for this issue.

Attachments:
https://github.com/tbeu/matio/files/8090326/id.001628.sig.06.src.007945.time.21810082.op.havoc.rep.2.trial.1496358.tar.gz

================= Bug Report (2/2) ==================
## Source: Red Hat Bugzilla
## URL: https://bugzilla.redhat.com/show_bug.cgi?id=2079986
## Description:
Bugzilla ID: 2079986
Title: CVE-2022-1515 matio: memory leak in Mat_VarReadNextInfo5() in mat5.c

Description
Guilherme de Almeida Suckevicz 2022-04-28 16:58:54 UTC
A memory leak was discovered in matio 1.5.21 and earlier in Mat_VarReadNextInfo5() in mat5.c via a crafted file. This issue can potentially result in DoS.

Reference:
https://github.com/tbeu/matio/issues/186

Upstream patch:
https://github.com/tbeu/matio/commit/b53b62b756920f4c1509f4ee06427f66c3b5c9c4


Comments:
Comment 1
Guilherme de Almeida Suckevicz 2022-04-28 16:59:08 UTC
Created matio tracking bugs for this issue:

Affects: epel-all [bug 2079987]

Build script:
#!/bin/bash
# Default build script template for C/C++ projects
set -eu

# Define configuration options
CONFIG_OPTS="--disable-shared"
CMAKE_OPTS="-DCMAKE_BUILD_TYPE=Debug"
MAKE_OPTS="-j$(nproc)"
BUILD_DIR="build"

# 1. Run build preparation scripts if they exist
for prep_script in buildconf autogen.sh bootstrap; do
  if [ -x "$prep_script" ]; then
    echo "Running $prep_script..."
    ./$prep_script
    break
  elif [ -f "$prep_script" ]; then
    echo "Found $prep_script but it's not executable, setting permissions..."
    chmod +x $prep_script
    ./$prep_script
    break
  fi
done

# 2. Handle different build systems
if [ -f "configure" ]; then
  echo "Found configure script, running with options: $CONFIG_OPTS"
  ./configure $CONFIG_OPTS

  echo "Building with make $MAKE_OPTS"
  make $MAKE_OPTS
elif [ -f "CMakeLists.txt" ]; then
  echo "Found CMakeLists.txt, using CMake build system"
  mkdir -p $BUILD_DIR
  cd $BUILD_DIR
  cmake $CMAKE_OPTS ..
  make $MAKE_OPTS
elif [ -f "Makefile" ] || [ -f "makefile" ]; then
  echo "Found Makefile, building with make $MAKE_OPTS"
  make $MAKE_OPTS
elif [ -f "meson.build" ]; then
  echo "Found meson.build, using Meson build system"
  mkdir -p $BUILD_DIR
  meson setup $BUILD_DIR .
  cd $BUILD_DIR
  ninja
elif [ -f "GNUmakefile" ]; then
  echo "Found GNUmakefile, building with make $MAKE_OPTS"
  make $MAKE_OPTS
elif [ -d ".git" ] && [ -f "Makefile.am" ]; then
  echo "Found Makefile.am, running autoreconf"
  autoreconf -i
  ./configure $CONFIG_OPTS
  make $MAKE_OPTS
else
  echo "WARNING: No recognized build system found!"
  echo "Trying generic approach:"
  
  # Try to detect common source patterns and compile them
  if ls *.c >/dev/null 2>&1 || ls *.cpp >/dev/null 2>&1 || ls *.cc >/dev/null 2>&1; then
    echo "Found C/C++ source files, attempting direct compilation"
    if ls *.cpp >/dev/null 2>&1 || ls *.cc >/dev/null 2>&1; then
      CXX=${CXX:-g++}
      echo "Compiling C++ sources with $CXX"
      $CXX -g -O1 -fsanitize=address -fno-omit-frame-pointer -o main *.cpp *.cc 2>/dev/null || true
    elif ls *.c >/dev/null 2>&1; then
      CC=${CC:-gcc}
      echo "Compiling C sources with $CC"
      $CC -g -O1 -fsanitize=address -fno-omit-frame-pointer -o main *.c 2>/dev/null || true
    fi
  fi
fi

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone https://github.com/tbeu/matio matio
RUN git -C matio checkout 15c9c59173eb217c7fefc74cc36dcb58f24a0d4a
WORKDIR $SRC/matio
COPY build.sh $SRC/

Additional files: