Issue 21443 - scope (failure) with a return breaks safety
Summary: scope (failure) with a return breaks safety
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 critical
Assignee: No Owner
URL:
Keywords: pull, safe, spec
Depends on:
Blocks:
 
Reported: 2020-12-02 11:15 UTC by Andrej Mitrovic
Modified: 2024-03-27 17:10 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Andrej Mitrovic 2020-12-02 11:15:37 UTC
-----
ulong get () @safe nothrow
{
    scope (failure) return 10;
    throw new Error("");
}

void main () @safe
{
    assert(get() == 10);  // passes
}
-----

It should not be allowed to do a `return` inside of a `scope (failure)`, because currently scope failure also handles Errors. In this case any Error thrown is not re-thrown, and the function simply returns a value.

That's a big hole in safety IMO.
Comment 1 Steven Schveighoffer 2022-06-08 01:35:18 UTC
I concur. Recently came up on the forums in response to a blog post I made: https://forum.dlang.org/post/tylpiqohdfqsiiqupfta@forum.dlang.org

Since an Error does not necessarily properly unwind the stack, just returning a normal error code doesn't reflect the gravity of the situation -- you should not be allowed to swallow Errors and continue.

My suggestion would be to rewrite the scope(failure) code as:

```d
try {
  ...
} catch(Error err) {
  // return 10; // not allowed
  abort("Cannot return from thrown Error");
} catch(Throwable) {
  return 10;
}
```

Which would allow code to still compile, but not allow Undefined Behavior.

I would suggest this still happen even inside @system code. If you want to circumvent, write out the try/catch yourself.

I'd also be OK with Andrej's suggestion (no return inside scope(failure), or anything like it, such as a goto outside the block).

I should note, the spec specifically allows this, as it forbids returns inside scope(exit) and scope(success), but purposefully leaves out scope(failure).
Comment 2 Dlang Bot 2022-07-05 14:09:16 UTC
@RazvanN7 created dlang/dmd pull request #14269 "Fix Issue 21443 - scope (failure) with a return breaks safety" fixing this issue:

- Fix Issue 21443 - scope (failure) with a return breaks safety

https://github.com/dlang/dmd/pull/14269
Comment 3 Dlang Bot 2022-07-07 14:18:17 UTC
dlang/dmd pull request #14269 "Fix Issue 21443 - scope (failure) with a return breaks safety" was merged into stable:

- 8ea4610d83d9c4b7aebc2ea52514885c02ef193d by RazvanN7:
  Fix Issue 21443 - scope (failure) with a return breaks safety

https://github.com/dlang/dmd/pull/14269
Comment 4 Dlang Bot 2022-07-09 16:31:52 UTC
dlang/dmd pull request #14280 "merge stable" was merged into master:

- 2c336dfa825c481f0a32f495ce26232e45d820a4 by RazvanN7:
  Fix Issue 21443 - scope (failure) with a return breaks safety

https://github.com/dlang/dmd/pull/14280