matio
matio copied to clipboard
Heap-based Buffer Overflow in strdup_vprintf
Hi, this is an issue found by fuzzing the current master branch.
Affected Projects
matio v1.5.28 (https://github.com/tbeu/matio)
Problem Type
CWE-122: Heap-based Buffer Overflow
Description
Summary
A heap-buffer-overflow vulnerability was discovered in the strdup_vprintf function defined in src/io.c at line 67. This issue occurs when processing certain files, leading to an out-of-bounds read and potential application crash.
PoC
Steps to reproduce: (According to OSS-Fuzz)
- Build it using the following commands :
git clone --depth 1 https://github.com/madler/zlib
git clone --depth 1 https://github.com/tbeu/matio.git matio
git clone --depth 1 --branch hdf5_1_14 https://github.com/HDFGroup/hdf5.git hdf5
cd matio/
#some env
export CC='clang'
export CFLAGS='-fsanitize=address,fuzzer-no-link -O1 -g'
export CXXFLAGS='-fsanitize=address,fuzzer -O1 -g'
export CXX='clang++'
export WORK=/fuzz/work
export SRC=/fuzz/project
export OUT=/fuzz/fuzzers
pushd "$SRC/zlib"
./configure --static --prefix="$WORK"
make -j$(nproc) CFLAGS="$CFLAGS -fPIC"
make install
popd
wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz
tar xvfvz autoconf-2.71.tar.gz
pushd autoconf-2.71
./configure
make
make install
popd
#build hdf5
pushd "$SRC"
cd hdf5
./autogen.sh
./configure --disable-shared --disable-deprecated-symbols --disable-hl --disable-parallel --disable-trace --disable-internal-debug --disable-asserts --disable-tests --disable-tools --with-pic --with-zlib="$WORK" --prefix="$WORK"
make -j$(nproc)
make install
popd
# build matio
./autogen.sh
./configure --prefix="$WORK" --disable-shared --with-hdf5="$WORK" --with-zlib="$WORK"
make -j$(nproc)
make install
MATIO_INCLUDE="$WORK/include"
MATIO_LIBS_NO_FUZZ="$WORK/lib/libmatio.a $WORK/lib/libhdf5.a $WORK/lib/libz.a"
MATIO_LIBS="$LIB_FUZZING_ENGINE $MATIO_LIBS_NO_FUZZ"
- Compile the fuzzer:
cd ./ossfuzz
for fuzzers in $(find . -name '*_fuzzer.cpp'); do
base=$(basename -s .cpp $fuzzers)
$CXX $CXXFLAGS -std=c++11 -I$MATIO_INCLUDE $fuzzers -o $OUT/$base $MATIO_LIBS
done
- Run the fuzzer to trigger the segmentation fault:
./matio_fuzzer src_io.c_67_12
The invalid read access will cause AddressSanitizer to report a segmentation fault during the execution of the post-processing logic.
Report
=================================================================
==24885==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x611000001288 at pc 0x5ae75248ea7d bp 0x7ffc84447540 sp 0x7ffc84446cc8
READ of size 149 at 0x611000001288 thread T0
#0 0x5ae75248ea7c in printf_common(void*, char const*, __va_list_tag*) asan_interceptors.cpp.o
#1 0x5ae75252e555 in strdup_vprintf /fuzz/project/matio/src/io.c:67:12
#2 0x5ae75252e555 in mat_log /fuzz/project/matio/src/io.c:183:14
#3 0x5ae75252e555 in Mat_Critical /fuzz/project/matio/src/io.c:381:5
#4 0x5ae7525f5031 in InflateData /fuzz/project/matio/src/inflate.c:369:9
#5 0x5ae7525fa5c5 in ReadCompressedDoubleDataDouble /fuzz/project/matio/src/./read_data_impl.h:343:5
#6 0x5ae7525fa5c5 in ReadCompressedDoubleData /fuzz/project/matio/src/./read_data_impl.h:542:13
#7 0x5ae752556600 in Mat_VarRead5 /fuzz/project/matio/src/mat5.c:3849:38
#8 0x5ae7525e1285 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1692:45
#9 0x5ae7525e0f42 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1686:46
#10 0x5ae7525dd0d4 in Mat_VarReadNextInfo5 /fuzz/project/matio/src/mat5.c:5413:27
#11 0x5ae7525326fe in Mat_VarReadNextInfoPredicate /fuzz/project/matio/src/mat.c:2651:22
#12 0x5ae7525326fe in Mat_VarReadNextInfo /fuzz/project/matio/src/mat.c:2625:12
#13 0x5ae7525326fe in Mat_GetDir /fuzz/project/matio/src/mat.c:827:26
#14 0x5ae75252d138 in MatioRead(char const*) /fuzz/project/matio/ossfuzz/./matio_wrap.h:39:24
#15 0x5ae75252d45d in LLVMFuzzerTestOneInput /fuzz/project/matio/ossfuzz/./matio_fuzzer.cpp:30:12
#16 0x5ae7524535f3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x4665f3) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#17 0x5ae75243d36f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x45036f) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#18 0x5ae7524430c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/fuzz/cs/matio_fuzzer+0x4560c6) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#19 0x5ae75246cee2 in main (/fuzz/cs/matio_fuzzer+0x47fee2) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#20 0x77303640bd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#21 0x77303640be3f in __libc_start_main csu/../csu/libc-start.c:392:3
#22 0x5ae752437c34 in _start (/fuzz/cs/matio_fuzzer+0x44ac34) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
0x611000001288 is located 0 bytes to the right of 200-byte region [0x6110000011c0,0x611000001288)
allocated by thread T0 here:
#0 0x5ae7524efc6e in malloc (/fuzz/cs/matio_fuzzer+0x502c6e) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#1 0x5ae752554f16 in Mat_VarRead5 /fuzz/project/matio/src/mat5.c:3778:36
#2 0x5ae7525e1285 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1692:45
#3 0x5ae7525e0f42 in ReadNextStructField /fuzz/project/matio/src/mat5.c:1686:46
#4 0x5ae7525dd0d4 in Mat_VarReadNextInfo5 /fuzz/project/matio/src/mat5.c:5413:27
#5 0x5ae7525326fe in Mat_VarReadNextInfoPredicate /fuzz/project/matio/src/mat.c:2651:22
#6 0x5ae7525326fe in Mat_VarReadNextInfo /fuzz/project/matio/src/mat.c:2625:12
#7 0x5ae7525326fe in Mat_GetDir /fuzz/project/matio/src/mat.c:827:26
#8 0x5ae75252d138 in MatioRead(char const*) /fuzz/project/matio/ossfuzz/./matio_wrap.h:39:24
#9 0x5ae75252d45d in LLVMFuzzerTestOneInput /fuzz/project/matio/ossfuzz/./matio_fuzzer.cpp:30:12
#10 0x5ae7524535f3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x4665f3) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#11 0x5ae75243d36f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/fuzz/cs/matio_fuzzer+0x45036f) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#12 0x5ae7524430c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/fuzz/cs/matio_fuzzer+0x4560c6) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#13 0x5ae75246cee2 in main (/fuzz/cs/matio_fuzzer+0x47fee2) (BuildId: 69d0eac2c142cb2dc762c58d0e01e47ee83df8a8)
#14 0x77303640bd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
SUMMARY: AddressSanitizer: heap-buffer-overflow asan_interceptors.cpp.o in printf_common(void*, char const*, __va_list_tag*)
Shadow bytes around the buggy address:
0x0c227fff8200: 00 fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c227fff8210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c227fff8220: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa
0x0c227fff8230: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x0c227fff8240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c227fff8250: 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c227fff8260: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c227fff8270: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c227fff8280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c227fff8290: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c227fff82a0: 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
==24885==ABORTING
CVE-2025-2338 seems to have been associated with this issue.
I do not see what fails. Can you check if the error also occurs if #define HAVE_VSNPRINTF 0 is forced in matioConfig.h? Thanks!
Resolved by 7b31881ea1da30b075658502961dfcc95353d9ae.