It is possible to throw an immutable Exception and catch it as mutable. Using this immutable data can be modified.
Example Code:
class Dummy: Exception
{
int[] data;
@safe pure nothrow this(immutable int[] data) immutable
{
super("Dummy");
this.data = data;
}
}
@safe pure void modifyImmutable(immutable int[] data)
{
try
{
immutable Dummy e = new immutable Dummy(data);
throw e;
}
catch(Dummy e)
{
e.data[1] = 42;
}
}
@safe pure void main()
{
immutable int[] data = [1,2,3];
assert(data == [1,2,3]);
modifyImmutable(data);
assert(data == [1,42,3]);
}
Comment #1 by andrej.mitrovich — 2014-02-09T12:48:38Z
Interesting.. but I don't see how this can be solved except disallowing throwing non-mutable objects. Otherwise you'd end up in a situation where "try { } catch (Throwable) { }" could let an Exception through because it's non-mutable.
Comment #2 by andrej.mitrovich — 2014-02-09T12:49:16Z
Also since Exceptions can be chained I don't think it makes sense to allow throwing non-mutable objects.
Comment #3 by k.hara.pg — 2014-02-09T23:01:11Z
(In reply to comment #0)
At least, defining immutable constructor in derived classes of Throwable should be disallowed.
> class Dummy: Exception
> {
> int[] data;
> @safe pure nothrow this(immutable int[] data) immutable
> {
> super("Dummy");
--> during immutable object construction, mutable super constructor should not
be invoked.
> this.data = data;
> }
> }
Comment #4 by dlang-bot — 2022-12-16T13:00:39Z
@ntrel created dlang/dmd pull request #14706 "Fix Issue 12118 - Modify immutable data using throw" fixing this issue:
- Fix Issue 12118 - Modify immutable data using throw
https://github.com/dlang/dmd/pull/14706
Comment #5 by nick — 2022-12-16T17:02:26Z
comment #0:
> It is possible to throw an immutable Exception and catch it as mutable
Also, the exception is mutated when thrown so that is another safety violation if immutable:
https://github.com/dlang/dmd/blob/v2.101.1/druntime/src/rt/deh.d#L13-L21
comment #3:
> At least, defining immutable constructor in derived classes of Throwable should be disallowed.
That wouldn't disallow:
throw new immutable Exception("");
Comment #6 by dlang-bot — 2023-03-13T15:42:27Z
dlang/dmd pull request #14706 "Fix Issue 12118 - Modify immutable data using throw" was merged into master:
- 5e7700af332f69bcb887b558b421f29cfd4da21e by Nick Treleaven:
Fix Issue 12118 - Modify immutable data using throw
https://github.com/dlang/dmd/pull/14706