Hey my dude,
Great repository. Single header libraries are my favorite to review as well as use in my own projects. 😄
Finding
A signed integer overflow exists in json_ipow. The function declares its base parameter as int, allowing the squaring step base *= base in the binary-exponentiation loop to silently overflow when the intermediate base value reaches 10^8 (iteration 4 for any initial base = 10 and exp >= 16).
json_ipow implements binary (fast) exponentiation. In every loop iteration - including the final one, where the squared result is never used - the squaring base *= base is performed unconditionally:
|
JSON_INTERN json_number |
|
json_ipow(int base, unsigned exp) |
|
{ |
|
/* simple power function for json exponent numbers */ |
|
long res = 1; |
|
while (exp) { |
|
if (exp & 1) |
|
res *= base; |
|
exp >>= 1; |
|
base *= base; |
|
} return (json_number)res; |
|
} |
With base = 10 and exp = 22:
| Iteration |
exp & 1 |
Action on res |
exp after >>= 1 |
base after *= base |
| 1 |
0 |
— |
11 |
100 |
| 2 |
1 |
res = 100 |
5 |
10 000 |
| 3 |
1 |
res = 1 000 000 |
2 |
100 000 000 |
| 4 |
0 |
— |
1 |
10^16 → OVERFLOW |
| 5 |
1 |
res *= garbage |
0 |
(loop exits) |
100000000 * 100000000 = 10^16 exceeds INT_MAX = 2,147,483,647 ≈ 2.1×10^9.
In an uninstrumented production build the multiplication wraps silently, producing a garbage base value that propagates into res, corrupting the number conversion result.
Steps to Reproduce
I have attached the crashing input as well as a test harness.
harness.c
crash.json
Compile harness.c with the following:
$ clang -g -fsanitize=address,undefined \
-fno-omit-frame-pointer \
-fsanitize-recover=all \
-o harness harness.c
Then run the harness with the crashing input:
$ ./harness crash.json
../lib/json.h:715:14: runtime error: signed integer overflow: 100000000 * 100000000 cannot be represented in type 'int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../lib/json.h:715:14
json_convert result: 1.31244e+16
Environment
- vurtun / lib version:
5a3f3aba052e63ffae8eb0214c6bb8ffffedea3c
- System info:
Linux kali 6.18.12+kali-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.18.12-1kali1 (2026-02-25) x86_64 GNU/Linux
- Compiler:
Debian clang version 19.1.7
Cheers mate 🍺
Hey my dude,
Great repository. Single header libraries are my favorite to review as well as use in my own projects. 😄
Finding
A signed integer overflow exists in
json_ipow. The function declares itsbaseparameter as int, allowing the squaring stepbase *= basein the binary-exponentiation loop to silently overflow when the intermediate base value reaches 10^8 (iteration 4 for any initialbase = 10andexp >= 16).json_ipowimplements binary (fast) exponentiation. In every loop iteration - including the final one, where the squared result is never used - the squaringbase *= baseis performed unconditionally:lib/json.h
Lines 706 to 717 in 5a3f3ab
With
base = 10andexp = 22:100000000 * 100000000 = 10^16exceedsINT_MAX = 2,147,483,647 ≈ 2.1×10^9.In an uninstrumented production build the multiplication wraps silently, producing a garbage
basevalue that propagates intores, corrupting the number conversion result.Steps to Reproduce
I have attached the crashing input as well as a test harness.
harness.c
crash.json
Compile
harness.cwith the following:Then run the harness with the crashing input:
Environment
5a3f3aba052e63ffae8eb0214c6bb8ffffedea3cLinux kali 6.18.12+kali-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.18.12-1kali1 (2026-02-25) x86_64 GNU/LinuxDebian clang version 19.1.7Cheers mate 🍺