Download Latest Version Gravity v0.9.8 source code.zip (1.4 MB)
Email in envelope

Get an email when there's a new version of Gravity language

Home / 0.9.8
Name Modified Size InfoDownloads / 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 an identifier field, such as {"x":{"type":"function"}}, reached strlen(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=undefined builds 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 — the 0x/0b/0o prefix check read value[1] without confirming the token had two bytes, so a file whose last token was a bare 0 read one byte past the buffer (#446)
  • Crash (SIGFPE) folding a floating-point remainder — the optimizer folded % by truncating both operands to int64_t, so any divisor with 0 < |divisor| < 1 became an integer division by zero and killed the compiler on input as small as 1 % 0.5. Float remainder is now folded with remainder(), 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.0 folded to 1 where 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. New GRAVITY_INT_ADD/SUB/MUL/NEG/DIV/REM helpers do the arithmetic on the unsigned counterpart, so the values are unchanged but no longer undefined. They also cover GRAVITY_INT_MIN op -1, which on x86 faults in idiv rather than merely wrapping (#443)

Memory lifetime

  • Optional classes never releasedMath, File, JSON and ENV were leaked by every embedder that created and destroyed a VM, because gravity_core_free dropped 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 buffergravity -i handed its heap-allocated wrapper source to the compiler with is_static false, 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, plus json_bounds.c (make jsontest), 60 checks driving the JSON scanner directly. Run with test/loadbuffer/run_all.sh
  • A GitHub Actions workflow building with gcc and clang on Linux and macOS, plus a job built with -fsanitize=address,undefined that 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.md and CLAUDE.md documented a stale gravity.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

Source: README.md, updated 2026-08-05