| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| Gravity v0.9.8 source code.tar.gz | 2026-08-05 | 967.5 kB | |
| Gravity v0.9.8 source code.zip | 2026-08-05 | 1.4 MB | |
| README.md | 2026-08-05 | 4.6 kB | |
| Totals: 3 Items | 2.4 MB | 1 | |
Security and memory-safety release. Every crash below was reported by external researchers fuzzing the compiler and the bytecode loader, and each fix ships with a regression test.
Fixed
Bytecode loader (gravity -x / gravity_vm_loadbuffer)
These are reachable from attacker-controlled serialized bytecode, so they matter to any embedder that loads a .g file it did not produce itself.
- NULL dereference in
gravity_vm_loadbuffer— a function object without anidentifierfield, such as{"x":{"type":"function"}}, reachedstrlen(NULL)and killed the process. The loader now validates the shape of a JSON executable before trusting it: the root and every entry must be objects, the identifier must appear exactly once and be a string, and unknown object types are rejected. Malformed input becomes a load error instead of a crash (#444) - Signed 64-bit integer overflow in
json_parse_ex— the integer and exponent accumulators multiplied by 10 per digit with no range check, so any literal past 19 significant digits overflowed. Signed overflow is undefined in C: the parser stored a wrapped value, and-fsanitize=undefinedbuilds trapped with SIGILL. Both accumulators are range-checked now (#447) - Pointer-arithmetic overflow in the JSON scan loop — the scanner incremented its cursor unconditionally, so input ending while still inside a string or comment advanced the pointer past one-past-the-end, which is undefined behaviour. The loop now stops at the end of the buffer whatever state the scanner is in (#448)
Compiler
- Heap out-of-bounds read in
parse_number_expression— the0x/0b/0oprefix check readvalue[1]without confirming the token had two bytes, so a file whose last token was a bare0read one byte past the buffer (#446) - Crash (SIGFPE) folding a floating-point remainder — the optimizer folded
%by truncating both operands toint64_t, so any divisor with0 < |divisor| < 1became an integer division by zero and killed the compiler on input as small as1 % 0.5. Float remainder is now folded withremainder(), matching the runtime, and mixed Int/Float remainders are left to the VM because REM dispatches on the class of the left operand. This also corrects a silent wrong answer:5.5 % 2.0folded to1where the VM evaluates-0.5(#443) - Undefined behaviour in Int arithmetic — Gravity Ints wrap on overflow, but the wrap was done on signed operands in the VM fast path, in the
operator_int_*methods and in the constant folder. NewGRAVITY_INT_ADD/SUB/MUL/NEG/DIV/REMhelpers do the arithmetic on the unsigned counterpart, so the values are unchanged but no longer undefined. They also coverGRAVITY_INT_MIN op -1, which on x86 faults inidivrather than merely wrapping (#443)
Memory lifetime
- Optional classes never released —
Math,File,JSONandENVwere leaked by every embedder that created and destroyed a VM, becausegravity_core_freedropped a reference without the matching balance (#442) - Core reference leaked by every
gravity_compiler_run— the compiler took a reference to the core classes on each run and never gave it back, so the count never reached zero and the core was never torn down (#442) - Double free of the inline source buffer —
gravity -ihanded its heap-allocated wrapper source to the compiler withis_staticfalse, which passes ownership to the lexer; the lexer freed it and the CLI freed the same pointer again on the way out, aborting every inline run under a hardened allocator
Added
test/loadbuffer/— malformed JSON executables that must each be rejected as a load error without crashing, plusjson_bounds.c(make jsontest), 60 checks driving the JSON scanner directly. Run withtest/loadbuffer/run_all.sh- A GitHub Actions workflow building with gcc and clang on Linux and macOS, plus a job built with
-fsanitize=address,undefinedthat runs the unit tests, the fuzzing corpus and the loader tests through it
Changed
- The usage text now prints the real default output name,
gravity.g;README.mdandCLAUDE.mddocumented a stalegravity.json
Verification
351/351 unit tests and 12/12 loader tests pass, and the unit tests plus the 743-input fuzzing corpus run clean under -fsanitize=address,undefined.
Thanks
To the reporters of [#442], [#443], [#444], [#446], [#447] and [#448] for the detailed write-ups and minimized reproducers.
Full Changelog: https://github.com/marcobambini/gravity/compare/0.9.7...0.9.8