-
Notifications
You must be signed in to change notification settings - Fork 580
Open
Description
Hi, there is a potential bug in SurfaceData reachable when resizing and then deleting.
This bug was reproduced on 9dab8a4.
Description
What crashes
- SurfaceData stores its control-vertex indices in a Vtr::internal::StackBuffer<Index,20,true> (inline capacity 20).
- Calling SurfaceData::resizeCVs(28) grows the StackBuffer above its inline capacity and allocates dynamic storage.
- Calling SurfaceData::resizeCVs(0) shrinks it below the inline capacity. StackBuffer::SetSize() calls deallocate(), which frees the dynamic block and switches back to the inline buffer.
- Deallocate() does not null _dynamicData, and the destructor of StackBuffer then calls deallocate() again unconditionally (or equivalently without guarding on current storage), leading to a double free of the same pointer.
- AddressSanitizer reports a double-free at vtr/stackBuffer.h:100 in both the original reproducer and the minimized testcase.
Note that removing the first resize (s->resizeCVs(28)) no longer crashes with a double free.
POC
The following testcase demonstrates the bug:
testcase.cpp
#include "/fuzz/install/include/opensubdiv/bfr/surfaceData.h"
int main(){
using namespace OpenSubdiv::OPENSUBDIV_VERSION::Bfr::internal;
SurfaceData *s = new SurfaceData();
// Grow beyond inline capacity (SIZE = 20), which allocates dynamically
s->resizeCVs(28);
// Shrink to <= inline capacity, which frees the dynamic storage
s->resizeCVs(0);
// Destructor frees again: double-free
delete s;
return 0;
}
stdout
stderr
=================================================================
==1==ERROR: AddressSanitizer: attempting double-free on 0x50b000000040 in thread T0:
#0 0x55f8cecb398d in operator delete(void*) (/fuzz/test+0x10598d) (BuildId: 22f0dd75076291483718a1eb9bd66c7bb72c2319)
#1 0x55f8cecb56b1 in OpenSubdiv::v3_7_0::Vtr::internal::StackBuffer<int, 20u, true>::deallocate() /fuzz/install/include/opensubdiv/bfr/../vtr/stackBuffer.h:100:5
#2 0x55f8cecb5894 in OpenSubdiv::v3_7_0::Vtr::internal::StackBuffer<int, 20u, true>::~StackBuffer() /fuzz/install/include/opensubdiv/bfr/../vtr/stackBuffer.h:165:5
#3 0x55f8cecb5513 in OpenSubdiv::v3_7_0::Bfr::internal::SurfaceData::~SurfaceData() /fuzz/install/include/opensubdiv/bfr/surfaceData.h:38:36
#4 0x55f8cecb5478 in main /fuzz/testcase.cpp:11:3
#5 0x7f6b2c120d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#6 0x7f6b2c120e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#7 0x55f8cebda314 in _start (/fuzz/test+0x2c314) (BuildId: 22f0dd75076291483718a1eb9bd66c7bb72c2319)
0x50b000000040 is located 0 bytes inside of 112-byte region [0x50b000000040,0x50b0000000b0)
freed by thread T0 here:
#0 0x55f8cecb398d in operator delete(void*) (/fuzz/test+0x10598d) (BuildId: 22f0dd75076291483718a1eb9bd66c7bb72c2319)
#1 0x55f8cecb56b1 in OpenSubdiv::v3_7_0::Vtr::internal::StackBuffer<int, 20u, true>::deallocate() /fuzz/install/include/opensubdiv/bfr/../vtr/stackBuffer.h:100:5
#2 0x55f8cecb5559 in OpenSubdiv::v3_7_0::Vtr::internal::StackBuffer<int, 20u, true>::SetSize(unsigned int) /fuzz/install/include/opensubdiv/bfr/../vtr/stackBuffer.h:192:9
#3 0x55f8cecb54ce in OpenSubdiv::v3_7_0::Bfr::internal::SurfaceData::resizeCVs(int) /fuzz/install/include/opensubdiv/bfr/surfaceData.h:70:20
#4 0x55f8cecb545d in main /fuzz/testcase.cpp:9:6
#5 0x7f6b2c120d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
previously allocated by thread T0 here:
#0 0x55f8cecb312d in operator new(unsigned long) (/fuzz/test+0x10512d) (BuildId: 22f0dd75076291483718a1eb9bd66c7bb72c2319)
#1 0x55f8cecb5764 in OpenSubdiv::v3_7_0::Vtr::internal::StackBuffer<int, 20u, true>::allocate(unsigned int) /fuzz/install/include/opensubdiv/bfr/../vtr/stackBuffer.h:90:39
#2 0x55f8cecb55c9 in OpenSubdiv::v3_7_0::Vtr::internal::StackBuffer<int, 20u, true>::SetSize(unsigned int) /fuzz/install/include/opensubdiv/bfr/../vtr/stackBuffer.h:195:9
#3 0x55f8cecb54ce in OpenSubdiv::v3_7_0::Bfr::internal::SurfaceData::resizeCVs(int) /fuzz/install/include/opensubdiv/bfr/surfaceData.h:70:20
#4 0x55f8cecb5452 in main /fuzz/testcase.cpp:7:6
#5 0x7f6b2c120d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
SUMMARY: AddressSanitizer: double-free (/fuzz/test+0x10598d) (BuildId: 22f0dd75076291483718a1eb9bd66c7bb72c2319) in operator delete(void*)
==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/PixarAnimationStudios/OpenSubdiv /fuzz/src && \
cd /fuzz/src && \
git checkout 9dab8a47bfbb1388ec8388fe61f5f916e6123f38 && \
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++
# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates cmake ninja-build make \
&& rm -rf /var/lib/apt/lists/*
# Configure and build OpenSubdiv (CPU-only, static libs)
ENV CC=clang_wrapper CXX=clang_wrapper++
WORKDIR /fuzz/src
RUN cmake -S . -B build \
-G Ninja \
-D CMAKE_BUILD_TYPE=Release \
-D CMAKE_INSTALL_PREFIX=/fuzz/install \
-D BUILD_SHARED_LIBS=OFF \
-D NO_DOC=1 -D NO_EXAMPLES=1 -D NO_TUTORIALS=1 -D NO_REGRESSION=1 -D NO_PTEX=1 \
-D NO_OMP=1 -D NO_TBB=1 -D NO_CUDA=1 -D NO_OPENCL=1 -D NO_CLEW=1 -D NO_OPENGL=1 -D NO_METAL=1 \
-D NO_MACOS_FRAMEWORK=1
RUN cmake --build build --target install -- -vBuild Command
clang++-17 -fsanitize=address -g -O0 -o /fuzz/test /fuzz/testcase.cpp -I/fuzz/install/include -L/fuzz/install/lib -losdCPU && /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 -losdCPU && /fuzz/test"Additional Info
This testcase was discovered by STITCH, an autonomous fuzzing system. All reports are reviewed manually (by a human) before submission.
Metadata
Metadata
Assignees
Labels
No labels