Skip to content

Wrong pointer from captured field #23792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jonascloud opened this issue May 4, 2025 · 2 comments
Closed

Wrong pointer from captured field #23792

jonascloud opened this issue May 4, 2025 · 2 comments
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@jonascloud
Copy link

Zig Version

0.14.0

Steps to Reproduce and Observed Behavior

Hey,

I believe I've encountered a bug in the following Zig code. The function below returns a pointer to a captured field (self.bar) from a recursive function. In debug mode (when running zig build test), the code works fine. However, when using the -Doptimize flag, the returned pointer is incorrect.

Here is the problematic code:

const Foo = struct {
    bar: ?u32 = null,
    pub fn get(self: *Foo) !*const u32 {
        if (self.bar) |b| {
            return &b;
        } else {
            self.bar = 0;
            return self.get();
        }
    }
};

pub fn main() !void {
    var foo: Foo = .{};
    const bar = try foo.get();
    std.debug.print("{}", .{bar.*});

    std.debug.assert(bar.* == 0);
}

The code compiles correctly if I return the field directly without specifying a const pointer and let the compiler handle it. Using |*b| also works fine.

Regards,
Jonas

Expected Behavior

Function returns the correct pointer or &b is disallowed.

@jonascloud jonascloud added the bug Observed behavior contradicts documented or intended behavior label May 4, 2025
@milogreg
Copy link

milogreg commented May 4, 2025

b is not an alias for bar's u32 component, it is a constant local variable equal to bar's u32 component. A pointer to a variable will not be valid outside of the variable's scope, so you are invoking undefined behavior by dereferencing the pointer returned by get.

@jonascloud
Copy link
Author

Ah, yes. That's probably what's happening, thank you. b is a "copy" of the underlying memory and there are no guarantees, that this copy lives after the scope ends.
Referencing "introduce runtime safety for dangling stack pointers" and closing as duplicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

2 participants