-
Notifications
You must be signed in to change notification settings - Fork 761
Description
Hi, there is a potential bug in meep::grid_volume::str reachable via normal use.
This bug was reproduced on 0b21c67.
Description
The following testcase creates a meep::grid_volume and then tries to print it to a fixed size buffer.
Inside meep::grid_volume::str, it uses sprintf repeatedly with a pattern like:
written += snprintf(buffer + written, buflen - written, ...)
However, snprintf actually returns the number of bytes that would have been written, not the number of bytes that were actually written. Hence written can become larger than buflen, and then subsequent snprintf calls will overflow.
POC
The following testcase demonstrates the bug:
testcase.cpp
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include "/fuzz/install/include/meep/mympi.hpp"
#include "/fuzz/install/include/meep/vec.hpp"
extern "C" {
#include "/fuzz/install/include/meep/meep-config.h"
}
#include "/fuzz/install/include/meep/material_data.hpp"
#include "/fuzz/install/include/meep/adjust_verbosity.hpp"
#include "/fuzz/install/include/meep.hpp"
#include "/fuzz/install/include/meep/meepgeom.hpp"
int main() {
// Simple, benign 3D grid; no crafted parameters needed
meep::grid_volume gv = meep::vol3d(10.0, 11.0, 9.0, 1.0);
// Caller-provided stack buffer
char buf[128];
// This call overflows buf[] inside meep::grid_volume::str
const char *s = gv.str(buf, sizeof(buf));
// Use the result to prevent optimizing away
if (s) puts(s);
return 0;
}
stdout
stderr
=================================================================
==1==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fd4ddc00397 at pc 0x56460742db52 bp 0x7ffc08e0f920 sp 0x7ffc08e0f0c0
WRITE of size 3 at 0x7fd4ddc00397 thread T0
#0 0x56460742db51 in vsnprintf (/fuzz/test+0x50b51) (BuildId: 33b5038da7b3b4d3720d97aa1dcfb185543a5654)
#1 0x56460742f430 in snprintf (/fuzz/test+0x52430) (BuildId: 33b5038da7b3b4d3720d97aa1dcfb185543a5654)
#2 0x7fd4e0167240 in meep::grid_volume::str(char*, unsigned long) (/fuzz/install/lib/libmeep.so.35+0x212240) (BuildId: 71fc55fe5df6d220df7947efe4917ac005e82c0e)
#3 0x5646074e459c in main /fuzz/testcase.cpp:22:22
#4 0x7fd4dfa05d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#5 0x7fd4dfa05e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#6 0x564607409314 in _start (/fuzz/test+0x2c314) (BuildId: 33b5038da7b3b4d3720d97aa1dcfb185543a5654)
Address 0x7fd4ddc00397 is located in stack of thread T0 at offset 407 in frame
#0 0x5646074e441f in main /fuzz/testcase.cpp:16
This frame has 2 object(s):
[32, 192) 'gv' (line 18)
[256, 384) 'buf' (line 20) <== Memory access at offset 407 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/fuzz/test+0x50b51) (BuildId: 33b5038da7b3b4d3720d97aa1dcfb185543a5654) in vsnprintf
Shadow bytes around the buggy address:
0x7fd4ddc00100: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x7fd4ddc00180: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
0x7fd4ddc00200: f1 f1 f1 f1 00 00 00 00 00 00 00 00 00 00 00 00
0x7fd4ddc00280: 00 00 00 00 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2
0x7fd4ddc00300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7fd4ddc00380: f3 f3[f3]f3 00 00 00 00 00 00 00 00 00 00 00 00
0x7fd4ddc00400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fd4ddc00480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fd4ddc00500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fd4ddc00580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7fd4ddc00600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==1==ABORTING
Steps to Reproduce
The crash was triaged with the following Dockerfile:
Dockerfile
# Ubuntu 22.04 with some packages pre-installed
FROM hgarrereyn/stitch_repro_base@sha256:3ae94cdb7bf2660f4941dc523fe48cd2555049f6fb7d17577f5efd32a40fdd2c
RUN git clone https://github.com/NanoComp/meep /fuzz/src && \
cd /fuzz/src && \
git checkout 0b21c6745180abf37f2f65d37b7f301531e64af7 && \
git submodule update --init --remote --recursive
ENV LD_LIBRARY_PATH=/fuzz/install/lib
ENV ASAN_OPTIONS=hard_rss_limit_mb=1024:detect_leaks=0
RUN echo '#!/bin/bash\nexec clang-17 -fsanitize=address -O0 "$@"' > /usr/local/bin/clang_wrapper && \
chmod +x /usr/local/bin/clang_wrapper && \
echo '#!/bin/bash\nexec clang++-17 -fsanitize=address -O0 "$@"' > /usr/local/bin/clang_wrapper++ && \
chmod +x /usr/local/bin/clang_wrapper++
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
autoconf automake libtool pkg-config gfortran make \
libctl-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /fuzz/src
RUN CC=clang_wrapper CXX=clang_wrapper++ \
./autogen.sh \
--prefix=/fuzz/install \
--without-python \
--without-scheme \
--without-hdf5 \
--with-mpi=no \
--with-openmp=no
RUN make -j"$(nproc)" && make installBuild Command
clang++-17 -fsanitize=address -g -O0 -o /fuzz/test /fuzz/testcase.cpp -I/fuzz/install/include -L/fuzz/install/lib -lmeep -lm && /fuzz/testReproduce
- Copy
Dockerfileandtestcase.cppinto a local folder. - Build the repro image:
docker build . -t repro --platform=linux/amd64- Compile and run the testcase in the image:
docker run \
-it --rm \
--platform linux/amd64 \
--mount type=bind,source="$(pwd)/testcase.cpp",target=/fuzz/testcase.cpp \
repro \
bash -c "clang++-17 -fsanitize=address -g -O0 -o /fuzz/test /fuzz/testcase.cpp -I/fuzz/install/include -L/fuzz/install/lib -lmeep -lm && /fuzz/test"Additional Info
This testcase was discovered by STITCH, an autonomous fuzzing system. All reports are reviewed manually (by a human) before submission.