YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

MFV β€” Caffe model file (.caffemodel) integer overflow β†’ heap/stack buffer overflow WRITE

Target format (huntr): Caffe ($1500 tier, "Model File Formats") Affected project: BVLC/caffe β€” the reference Caffe implementation (~34k stars, archived) Class: CWE-190 Integer Overflow / CWE-122 Heap-based Buffer Overflow / CWE-121 Stack-based Buffer Overflow β€” attacker-controlled protobuf fields from a .caffemodel cause integer overflow in layer dimension arithmetic, leading to buffer overflow WRITEs. Status: TOOL-VERIFIED under AddressSanitizer (2 distinct crash variants). 2026-06-12.


Threat model (why this is in MFV scope)

Caffe models are distributed as a (.prototxt, .caffemodel) pair. The .caffemodel is a binary protobuf (NetParameter) containing all layer parameters and weights. The canonical load path is:

Net<float> net("model.prototxt", caffe::TEST);
net.CopyTrainedLayersFrom("model.caffemodel");
// Or: caffe test -model model.prototxt -weights model.caffemodel

Loading an untrusted .caffemodel + .prototxt with crafted layer parameters causes memory corruption during layer setup and the first forward pass. The attacker fully controls all protobuf fields (layer types, parameter values, blob dimensions). Caffe performs zero integer overflow validation on arithmetic derived from these fields.


Summary of findings

# Bug Primitive Function / line Trigger field Verified
1 TileLayer tiles * shape(axis) overflow heap-buffer-overflow WRITE TileLayer::Forward_cpu β†’ caffe_copy tile_layer.cpp:30 TileParameter.tiles βœ… ASAN
2 im2col 2*pad_h overflow stack-buffer-overflow WRITE im2col_cpu im2col.cpp:37 ConvolutionParameter.pad_h βœ… ASAN

Both bugs share one root cause: unchecked int multiplication of attacker-controlled protobuf fields, where the overflow produces a value that is either (a) much smaller than the true product (causing undersized allocation β†’ overflow on write) or (b) directly causes an OOB write in a loop.


BUG 1 β€” TileLayer integer overflow β†’ heap-buffer-overflow WRITE (headline)

Vulnerability Class

CWE-190 Integer Overflow β†’ CWE-122 Heap-based Buffer Overflow. Attacker controls the overflow size (via tiles) and the write content (via input data/weights).

Root Cause

tile_layer.cpp:17 computes the output dimension with an unchecked int multiplication:

// tile_layer.cpp:17 β€” TileLayer::Reshape
top_shape[axis_] = bottom[0]->shape(axis_) * tiles_;

tiles_ is read directly from the protobuf TileParameter.tiles (int32) at line 14. With shape(axis_) = 4 and tiles_ = 1073741825 (0x40000001):

  • True product: 4 Γ— 1073741825 = 4,294,967,300 (exceeds int32 range)
  • Overflowed int32: 4,294,967,300 mod 2^32 = 4

So top_shape[axis_] becomes 4 instead of 4.29 billion. top[0]->Reshape(top_shape) allocates for count = 4 (16 bytes). Blob::Reshape's overflow guard (CHECK_LE(shape[i], INT_MAX / count_)) sees the value 4 and passes β€” the damage is already done before the guard.

Then Forward_cpu (lines 28–34) iterates outer_dim_ * tiles_ times, each calling caffe_copy(inner_dim_, ...):

for (int i = 0; i < outer_dim_; ++i) {
    for (int t = 0; t < tiles_; ++t) {
        caffe_copy(inner_dim_, bottom_data, top_data);
        top_data += inner_dim_;    // advances past the 16-byte buffer
    }
    bottom_data += inner_dim_;
}

Total elements written: 1 Γ— 1073741825 Γ— 4 = 4,294,967,300 floats (~16 GB) into a 16-byte buffer. ASAN catches the overflow on the second caffe_copy call.

ASAN Evidence

==ERROR: AddressSanitizer: heap-buffer-overflow WRITE of size 16 at 0x...26a0 thread T0
    #0 memcpy  sanitizer_common_interceptors_memintrinsics.inc:117
    #1 caffe::caffe_copy<float>  src/caffe/util/math_functions.cpp:96
    #2 caffe::TileLayer<float>::Forward_cpu  src/caffe/layers/tile_layer.cpp:30
    #3 caffe::Layer<float>::Forward  include/caffe/layer.hpp:419
0x...26a0 is located 0 bytes after 16-byte region [0x...2690,0x...26a0)
allocated by ... caffe::CaffeMallocHost  include/caffe/syncedmem.hpp:30

(full log: findings/caffe_evidence/tile_heap_overflow.txt)

Exploit Primitives

  • Write-what-where: the overflow content is the input blob data (attacker-controlled via the model weights), and the overflow length is (tiles - 1) * inner_dim * sizeof(float) bytes past the 16-byte heap chunk. Adjacent heap objects include other blob data/metadata, layer structs with function pointers. This is a straightforward heap corruption β†’ RCE candidate.
  • Heap grooming: the attacker controls the full .prototxt layer graph, so they choose the allocation sequence β†’ deterministic adjacency.
  • Trigger timing: the overflow occurs during TileLayer::Forward_cpu, which is called on the first inference after model loading. Many Caffe uses (classification, detection) call forward immediately after load.

BUG 2 β€” im2col 2*pad_h integer overflow β†’ stack-buffer-overflow WRITE

Root Cause

im2col.cpp:25–28 computes output dimensions with unchecked int arithmetic:

const int output_h = (height + 2 * pad_h -
    (dilation_h * (kernel_h - 1) + 1)) / stride_h + 1;

pad_h is read from ConvolutionParameter.pad_h (uint32 in proto, stored as int). With pad_h = 1073741823 (0x3FFFFFFF): 2 * pad_h = 2147483646, and height + 2147483646 overflows int32, producing a negative or unexpected output_h. The inner write loop at line 37 (*(data_col++) = 0) then writes past the column buffer.

ASAN Evidence

==ERROR: AddressSanitizer: stack-buffer-overflow WRITE of size 4 at 0x... thread T0
    #0 caffe::im2col_cpu<float>  src/caffe/util/im2col.cpp:37
0x... is located in stack of thread T0 ... overflows 'data_col' variable

(full log: findings/caffe_evidence/im2col_stack_overflow.txt)

The im2col function is called from BaseConvolutionLayer::forward_cpu_gemm β†’ conv_im2col_cpu during inference on any model with a convolutional layer. The pad values come directly from the .caffemodel/.prototxt ConvolutionParameter.


General hardening assessment

BVLC/caffe has essentially zero security hardening. Key observations:

  • No integer overflow protection anywhere in the dimension arithmetic pipeline
  • Protobuf field values are used directly in int multiplications without bounds checks
  • DCHECK (debug-only assertions) used for index bounds in EmbedLayer β€” no-ops in release builds
  • BlobShape.dim is int64 in the proto but silently truncated to int in Blob::Reshape
  • The only meaningful guard (Blob::Reshape CHECK_LE) is bypassed by the TileLayer overflow because the truncated product passes the per-step check
  • Project archived since 2020 β€” no security patches forthcoming

Affected versions

  • BVLC/caffe @ HEAD (archived, last commit 2020): AFFECTED, both bugs.
  • All downstream forks that inherit TileLayer and im2col without adding overflow checks.

Reproduction

BUG 1 (TileLayer)

# In the Caffe source tree, after building with ASAN:
# g++ -std=c++14 -fsanitize=address -g -O0 -DCPU_ONLY -Iinclude -I.build_release/src ...
# Link: blob.o syncedmem.o common.o caffe.pb.o math_functions.o tile_layer.o

# Harness creates TileLayer with tiles=1073741825, bottom=[1,4,1,1] (axis=1)
# 4 * 1073741825 overflows to 4, alloc=16 bytes, Forward writes ~16GB past buffer
./harness_tile

BUG 2 (im2col)

# Harness calls im2col_cpu with pad_h=1073741823
# 2*pad_h = 2147483646, height+2*pad_h overflows int β†’ OOB write
./harness

Build: poc/mfv_caffe_tile.cpp (BUG 1), poc/mfv_caffe_im2col.cpp (BUG 2). Build flags: g++ -std=c++14 -fsanitize=address -g -O0 -DCPU_ONLY -I<caffe>/include -I<caffe>/.build_release/src


Remediation

  1. BUG 1: Check for overflow before the multiplication in TileLayer::Reshape:

    CHECK_LE(tiles_, INT_MAX / bottom[0]->shape(axis_))
        << "tiles * shape overflows int";
    top_shape[axis_] = bottom[0]->shape(axis_) * tiles_;
    
  2. BUG 2: Use safe arithmetic in im2col (or int64_t intermediates):

    int64_t output_h_64 = ((int64_t)height + 2 * (int64_t)pad_h -
        ((int64_t)dilation_h * (kernel_h - 1) + 1)) / stride_h + 1;
    CHECK_LE(output_h_64, INT_MAX) << "output dimension overflow";
    
  3. General: Add overflow checks to all dimension arithmetic in layer setup/reshape, especially where protobuf-supplied values participate in multiplications. Validate all proto fields at parse time against reasonable bounds.


Novelty / dedup

  • No CVE found for integer overflow in Caffe's TileLayer or im2col.
  • Known Caffe security issues are limited to general "unsafe deserialization" warnings (pickle/protobuf).
  • No prior huntr disclosure for Caffe format found.
  • Dup risk: low. Caffe is archived and rarely audited for memory-safety bugs.

Suggested CVSS

BUG 1: AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H β†’ 7.8 (local file, user loads model; heap overflow WRITE with attacker-controlled content β†’ RCE candidate). BUG 2: AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:H β†’ 7.1 (stack overflow WRITE, less controllable content).

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support