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

Check out the documentation for more information.

Caffe: int64→int32 Truncation in BlobShape Parsing — Shape Corruption / DoS

Status: CONFIRMED — READY TO SUBMIT

Severity: Medium (P3) — NOT Critical/P1

⚠️ RCE RESEARCH RESULT: NOT ACHIEVABLE

The copy loop in FromProto() is bounded by count_ (not proto.data_size()), and a CHECK_EQ(count_, proto.data_size()) guard fires before any write. SyncedMemory has no virtual functions (no vtable to overwrite). This is a real bug with real impact, but severity is Medium, not Critical.


Target

  • Repo: BVLC/caffe
  • Platform: huntr.com
  • Format: .caffemodel (protobuf)

Root Cause

BlobShape.dim is declared as int64 in caffe.proto but cast to int32 at:

  • src/caffe/blob.cpp:40shape_vec[i] = shape.dim(i) (no range check)
  • src/caffe/blob.cpp:298shape[i] = proto.shape().dim(i) (no range check)

A dim value of 0x100000001 (int64) truncates to 1 (int32) → count_ = 1.

Impact: Two Exploitable Effects

Effect 1: Controlled Process Abort (DoS)

Set dim = 0x100000001 (truncates to 1) + data[] with >1 entries. CHECK_EQ(count_=1, proto.data_size()=N)LOG(FATAL) → process abort. Attacker controls WHEN Caffe crashes by controlling data count.

Effect 2: Silent Shape Corruption

Set dim = 0x100000001 (truncates to 1) + exactly 1 data entry. CHECK_EQ(1, 1) passes. Blob accepted with shape [1] when it should be [4294967297]. Model that expects a 4B-element tensor operates on a 1-element blob. Impact: adversarial inference manipulation / silent wrong-model behavior.

Why NOT a Heap Overflow

// FromProto() — blob.cpp:315-320
CHECK_EQ(count_, proto.data_size());   // ABORTS if mismatch
for (int i = 0; i < count_; ++i) {    // bounded by count_, not proto.data_size()
    data_vec[i] = proto.data(i);       // only writes count_ elements
}

The CHECK guard fires before any write. Loop uses count_, not proto.data_size(). SyncedMemory has no virtual functions. No vtable overwrite possible.

Vulnerable Files

File Line Issue
src/caffe/blob.cpp 40 shape_vec[i] = shape.dim(i) — int64→int32, no range check
src/caffe/blob.cpp 298 shape[i] = proto.shape().dim(i) — same in FromProto
src/caffe/proto/caffe.proto BlobShape repeated int64 dim consumed as int32

PoC Files

  • poc_caffe_truncation.py — demonstrates both DoS and silent corruption effects

Reproduction

python poc_caffe_truncation.py dos      # controlled process abort
python poc_caffe_truncation.py corrupt  # silent shape corruption

Fix

// blob.cpp — Reshape(const BlobShape& shape):
for (int i = 0; i < shape.dim_size(); ++i) {
    CHECK_LE(shape.dim(i), INT_MAX) << "BlobShape dim exceeds INT_MAX";
    CHECK_GE(shape.dim(i), 0) << "BlobShape dim is negative";
    shape_vec[i] = static_cast<int>(shape.dim(i));
}

Note

Submit this SEPARATELY from caffe-oom-poc (the INT_MAX boundary case OOM bug). These are distinct vulnerabilities with different root causes and effects.

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