Skip to content

Conversation

jedisct1
Copy link
Contributor

Catch simple but common cases of returning pointers and slices to stack-allocated memory.

While not a complete solution to stack escape detection, this is still useful and has identified bugs in real-world projects.

Currently detects:

  • Direct pointers to local variables
  • Pointers to struct fields of stack-allocated structs
  • Array-to-slice conversions of stack arrays

This prevents undefined behavior from dangling stack references that would otherwise only be caught at runtime (if at all).

Elements are computed at comptime, so don't declare them as "var".
Catch simple but common cases of returning pointers and slices to
stack-allocated memory.

While not a complete solution to stack escape detection, this is
still useful and has identified bugs in real-world projects.

Currently detects:

- Direct pointers to local variables
- Pointers to struct fields of stack-allocated structs
- Array-to-slice conversions of stack arrays

This prevents undefined behavior from dangling stack references that
would otherwise only be caught at runtime (if at all).
@andrewrk
Copy link
Member

andrewrk commented Sep 19, 2025

Please take note of #25287. Feel free to file a proposal to challenge the status quo language semantics.

edit: already rejected in #5725

@andrewrk
Copy link
Member

Given that it is legal for a function to return an undefined pointer, this constitutes a breaking language change that needs to be specified in a language change proposal, which has been rejected in #5725. Feel free to provide an argument to revive the proposal.

A compiler enhancement to address this problem that does not change language semantics would be to use your same detection logic here, but rather than emitting a compile error, return undefined rather than the pointer to local. This will cause the problem to be detected at runtime in safe build modes due to the pointer address 0xaaaaaaaaaaaaaaaa being unmappable.

@jedisct1 jedisct1 closed this Sep 19, 2025
@andrewrk
Copy link
Member

You don't like my counter proposal?

@Rexicon226
Copy link
Contributor

How does your proposal not violate the zen?

  • Compile errors are better than runtime crashes.

@andrewrk
Copy link
Member

I don't really get your point. The language intentionally allows it, so it cannot be a compile error. It sounds like you want to make an argument to change the language. If that is your intention, then please go do that. Quoting the Zen is not an argument.

If the reasoning in the rejected proposal is not clear, then please construct a steel man argument to the best of your ability and then argue against it. This is the path towards getting what you want.

@Rexicon226
Copy link
Contributor

My statement was not an argument but genuine question. I don't mean to discuss this on a closed issue, but I do want to clarify what I'm confused about. I have carefully (I hope) read through #5725. Unfortunately none of the feedback was ever addressed so it is difficult to actually construct an argument against anything, since nothing was said counter to the points already made.

My thoughts are as follows,

  1. If the problem with C making this check portable is defining what a stack is, how does this issue translate over to the runtime detection in Zig proposal? The runtime detect proposal already implies that the Zig Abstract Machine has a stack, since otherwise compiling for targets which don't have one, or some special circumstance, wouldn't result in panics. Perhaps this is something that needs to be clarified in that issue? It is not clear to me what the behaviour would be.
  2. It was mentioned that we would need to perform analysis on whether the pointer was deferenced. Could you provide me an example (I have not found one described yet, apologies) where it makes sense or is required to return a pointer to a local and then not dereference it - thus not triggering the runtime check. If such an example does not exist, what reason is there to not compile error when we know for a fact that a reference to a local variable is returned and there is no possible behaviour afterwards in regards to that reference that could makes sense.
  3. And combining the above two points, if we agree that the Zig Abstract Machine has a stack, on which returning references to locals is illegal, then I see no reason to not take the Zen to heart and compile error instead of a runtime error (or maybe not even, if the pointer is never derefenced).

@andrewrk
Copy link
Member

Extracted my code review here into #25313

Also opened #25312

@andrewrk
Copy link
Member

I amended #25312 to include all the test cases that were in this patch. All of them can and should be caught by ast-check rather than Sema.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants