Skip to content

256 nested with panics: scope_depth is a u8 #35

Description

@wyattgill9
$ fix eval --expr "$(python3 -c 'print("with { a = 1; }; "*255 + "a")')"
1

$ fix eval --expr "$(python3 -c 'print("with { a = 1; }; "*256 + "a")')"
thread 16530570 panic: integer overflow

scope_depth is a u8 (src/expr/compiler/context.zig:117), and beginScope increments it unguarded.

The panic is the good case. In ReleaseFast the increment wraps to 0, and endScope (src/expr/compiler/scope.zig:20) then pops against a bogus depth:

pub fn endScope(self: *Compiler) void {
    self.scope_depth -= 1;
    while (self.locals.items.len > 0) {
        const local = self.locals.items[self.locals.items.len - 1];
        if (local.depth <= self.scope_depth) break;
        _ = self.locals.pop();
    }
}

With a wrapped scope_depth the wrong locals are popped and the result is a silent scoping bug rather than a crash.

declareLocal already handles its own limit properly with error.TooManyLocals; the same treatment here would be consistent.


fix 0.3.0 at 1f1a99cf, built -Doptimize=ReleaseSafe with Zig 0.16.0, darwin/aarch64. Reference implementation is Nix 2.34.8.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions