Skip to content

What's New in v1.12

"The Hardening Release" — memory-safety fixes, deeper concurrency, and a warning-clean build.

Three of the fixes below are genuine bugs that shipped in v1.11.0. Upgrading is recommended. Every memory fix was verified under AddressSanitizer.

Highlights

  • String concat use-after-free — fixed. Reusing a concatenation result as a later operand no longer corrupts or double-frees the string.
  • print / println double-free — fixed. Printing a fresh interpolated string no longer releases it twice.
  • Database / JSON heap overflow — fixed. Db.query, Db.query_params, and Json.keys now grow their buffers instead of overflowing on large results.
  • String interpolation no longer truncates at 512 bytes. Interpolated strings of any length round-trip intact.
  • Cooperative Time::sleep inside fire-and-forget spawn — sleeping yields to other tasks instead of blocking the worker thread.
  • Warning-clean build under -Wall -Wextra.

Memory safety

Wyn uses automatic reference counting (ARC), so these were real correctness bugs, not just leaks — several could corrupt live data.

String concat use-after-free

wyn
var a = "hello"
var b = " world"
var j = a + b        // j = "hello world"
var m = j + "!"      // reusing j as an operand
println(m)           // "hello world!" — was corrupt / double-freed before v1.12

wyn_string_concat_safe now always returns a distinct allocation, so an operand that is reused later stays valid.

wyn
var x = 42
println("x=${x}")    // fresh interpolated temp — was released twice before v1.12

Database / JSON heap overflow

Db.query / Db.query_params / Json.keys previously wrote unbounded results into fixed 64KB / 4KB buffers; a larger result overflowed the heap. They now grow as needed (verified on a ~168KB result).

String interpolation length

Interpolated strings longer than 511 bytes were silently cut. They now round-trip at any length.

Reference-count hardening

Heap detection for ARC now uses a dual sentinel, and two internal compiler buffers were made bounds-safe against overly long identifiers.

Concurrency

Cooperative Time::sleep

Inside the coroutine scheduler (fire-and-forget spawn), sleeping now yields to other tasks instead of blocking the worker thread:

wyn
fn worker(id: int) {
    Time::sleep(200)              // yields — other spawns keep running
    println("done ${id}")
}

fn main() {
    for i in 0..50 {
        spawn worker(i)
    }
    Time::sleep(300)
}

In one benchmark, 50 concurrent 200ms sleeps finished in ~0.21s instead of ~1.03s.

Note: awaited spawn and parallel { } run on the thread pool and still block during a sleep. Routing those onto the cooperative scheduler is on the roadmap.

Build & tooling

  • Warning-clean build under -Wall -Wextra.
  • Runtime library rebuild fixedmake now rebuilds libwyn_rt.a whenever a runtime source or header changes, so compiled programs never link a stale runtime.

Upgrading

bash
wyn --version        # should show 1.12.0

No source changes are required — v1.12.0 is a drop-in upgrade that fixes bugs present in v1.11.0.

See also

MIT License — v1.16