salvepilo commited on
Commit
6bf733b
·
verified ·
1 Parent(s): fc85531

Add standalone C++ reproducer

Browse files
Files changed (1) hide show
  1. reproducer.cpp +74 -0
reproducer.cpp ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Minimal reproducer for Gemma3 integer division-by-zero
2
+ // Mirrors the vulnerable code in src/models/gemma3.cpp:32
3
+ // and src/llama-model.cpp:1147-1171
4
+ //
5
+ // Compile: g++ -o reproducer reproducer.cpp -fsanitize=undefined -fno-sanitize-recover=all
6
+ // Run: ./reproducer
7
+
8
+ #include <cmath>
9
+ #include <cstdint>
10
+ #include <cstdio>
11
+ #include <cstring>
12
+ #include <array>
13
+ #include <stdexcept>
14
+ #include <string>
15
+
16
+ #define LLAMA_MAX_LAYERS 512
17
+
18
+ // Mirrors llama_hparams (simplified)
19
+ struct llama_hparams {
20
+ uint32_t n_embd = 3072; // from gemma3.embedding_length in GGUF
21
+ uint32_t n_layer_all = 62; // from gemma3.block_count = 62 → LLM_TYPE_27B
22
+ uint32_t n_embd_head_k_full = 0;
23
+
24
+ std::array<uint32_t, LLAMA_MAX_LAYERS> n_head_arr = {}; // all zeros — key missing from GGUF
25
+
26
+ uint32_t n_head(uint32_t il = 0) const {
27
+ return n_head_arr[il]; // returns 0 when key is absent
28
+ }
29
+ };
30
+
31
+ enum llm_type { LLM_TYPE_UNKNOWN, LLM_TYPE_1B, LLM_TYPE_4B, LLM_TYPE_8B, LLM_TYPE_12B, LLM_TYPE_27B };
32
+
33
+ int main() {
34
+ llama_hparams hparams;
35
+
36
+ // --- Mirrors llama-model.cpp:1147 (general hparams loader) ---
37
+ // When n_head() == 0, n_embd_head_k_full is set to 0
38
+ if (hparams.n_head() > 0) {
39
+ hparams.n_embd_head_k_full = hparams.n_embd / hparams.n_head();
40
+ } else {
41
+ hparams.n_embd_head_k_full = 0;
42
+ }
43
+
44
+ // --- Mirrors gemma3.cpp:20-32 (load_arch_hparams) ---
45
+ llm_type type = LLM_TYPE_UNKNOWN;
46
+ switch (hparams.n_layer_all) {
47
+ case 18: type = LLM_TYPE_UNKNOWN; break; // 270M
48
+ case 26: type = LLM_TYPE_1B; break;
49
+ case 32: type = LLM_TYPE_8B; break;
50
+ case 34: type = LLM_TYPE_4B; break;
51
+ case 48: type = LLM_TYPE_12B; break;
52
+ case 62: type = LLM_TYPE_27B; break; // <-- block_count=62 triggers this
53
+ default: type = LLM_TYPE_UNKNOWN; break;
54
+ }
55
+
56
+ printf("block_count = %u → type = %s\n", hparams.n_layer_all,
57
+ type == LLM_TYPE_27B ? "LLM_TYPE_27B" : "other");
58
+ printf("n_head(0) = %u (key absent from GGUF → stays 0)\n", hparams.n_head(0));
59
+ printf("n_embd = %u\n", hparams.n_embd);
60
+ printf("\nExecuting vulnerable line (gemma3.cpp:32):\n");
61
+ printf(" hparams.n_embd / hparams.n_head(0) = %u / %u\n",
62
+ hparams.n_embd, hparams.n_head(0));
63
+
64
+ // THE VULNERABLE COMPUTATION — mirrors gemma3.cpp:32 exactly
65
+ // On x86_64: SIGFPE (exit 136)
66
+ // On ARM64: silent UB (SDIV returns 0), UBSan aborts with "division by zero"
67
+ float f_attention_scale = (type == LLM_TYPE_27B)
68
+ ? 1.0f / std::sqrt(float(hparams.n_embd / hparams.n_head(0))) // INTEGER DIV BY ZERO
69
+ : 1.0f / std::sqrt(float(hparams.n_embd_head_k_full));
70
+
71
+ // Should never reach here on x86_64
72
+ printf("f_attention_scale = %f (should not reach here on x86_64)\n", f_attention_scale);
73
+ return 0;
74
+ }