Bug 18002 – assert subverts the type system with the messages that it accepts

Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-11-21T19:19:41Z
Last change time
2023-04-10T13:49:21Z
Keywords
accepts-invalid
Assigned to
No Owner
Creator
Jonathan M Davis

Comments

Comment #0 by issues.dlang — 2017-11-21T19:19:41Z
This code should not compile but does ===================== void main() { char[] message = "foo".dup; assert(0, message); } ===================== When assert fails, it gets converted to an AssertError, which - like all Throwables - takes a string for its message. So, the fact that assert accepts a char[] rather than a string means that either it's iduping what it's given or that it's implicitly converting char[] to immutable(char)[], which violates the type system. And as this D.Learn post demonstrates: http://forum.dlang.org/post/[email protected] if you go and pass it a slice of a static array, it does _not_ copy the contents. It's clearly slicing them, which means that it is implicitly converting the char[] to immutable(char)[], thus violating the type system, and in the case where you pass it a slice of a static array, you're then dealing with an invalid pointer. I don't know why assert accepts anything other than string for its message (particularly given that AssertError requires a string, and the message needs to be on the stack), but either it needs to be fixed so that it requires string, and passing it a char[] is an error, or the implementation needs to idup the message. I'm inclined to think that restricting it to string and forcing the user to idup the char[] in the rare case that that's what's wanted would be the better option, but either way, it needs to be fixed so that assert doesn't subvert the type system.
Comment #1 by hsteoh — 2017-11-21T19:33:06Z
*** Issue 18003 has been marked as a duplicate of this issue. ***
Comment #2 by hsteoh — 2017-11-21T19:35:00Z
See the code I posted in issue #18003. The compiler should reject any attempt to pass a slice of a local variable to assert().
Comment #3 by dfj1esp02 — 2017-11-22T12:31:25Z
The message is not necessarily static and immutability is only a requirement of default druntime implementation of assert failure handler, so it should be enough for the assert failure handler to idup the string before passing it to AssertError constructor.
Comment #4 by hsteoh — 2017-11-22T16:23:34Z
.idup may not be usable if the assert is triggered by an out-of-memory condition.
Comment #5 by razvan.nitu1305 — 2022-11-23T10:06:39Z
The compiler attempts to implicitly cast to `const(char)[]`. Since the assert does not actually modify the message that should be fine, however, because the lowering to _d_assert_msg is done in the gluelayer it does not check the type of the message argument (if the frontend did not reject the code it means that the implicit cast to const(char)[] was possible). This seems a bit iffy, however, I don't see this as being a problem in @safe code. > See the code I posted in issue #18003. The compiler should reject any attempt to pass a slice of a local variable to assert(). That behavior has now been deprecated provided that the function is marked @safe.