ybgwon96's picture
Upload 3 files
66f1af6 verified
Raw
History Blame Contribute Delete
1.31 kB
// Faithful isolation of the unchecked n_dims -> ne[2] stack overflow shared by koboldcpp's legacy
// ggml loaders (otherarch/gpt2_v1/v2/v3, gptj_v1/v2/v3, mpt_v3, llama_v2/v3, neox_v2/v3, rwkv_v2).
// e.g. gpt2_v2.cpp:269-273:
// int32_t ne[2] = {1,1};
// for (int i = 0; i < n_dims; ++i) { fin.read(&ne[i], sizeof(ne[i])); nelements *= ne[i]; }
// n_dims is read straight from the model file with no `n_dims<=2` check -> n_dims>=3 writes past the
// 2-element stack array with fully attacker-controlled bytes -> stack smash (CWE-787).
// Build: c++ -O2 -g -fstack-protector-all ndims_repro.cpp -o ndims_repro Run: ./ndims_repro 100000
#include <cstdio>
#include <cstdlib>
#include <cstdint>
int main(int argc, char** argv){
int32_t n_dims = argc>1 ? atoi(argv[1]) : 100000; // attacker file field, unbounded
int32_t nelements = 1;
int32_t ne[2] = { 1, 1 }; // fixed 2-element stack array
fprintf(stderr, "n_dims=%d writing past int32_t ne[2] ...\n", n_dims); fflush(stderr);
for (int i = 0; i < n_dims; ++i) { // no bound check
ne[i] = 0x41414141; // = fin.read() of attacker bytes
nelements *= ne[i];
}
fprintf(stderr, "survived (unexpected) %d\n", nelements);
return 0;
}