DIP33: A standard exception hierarchy
Dmitry Olshansky
dmitry.olsh at gmail.com
Fri Apr 5 07:06:21 PDT 2013
04-Apr-2013 23:16, Ali Çehreli пишет:
> > All you need is one example where it would remove the wrong file,
>
> $ dmd deneme.d -ofdeneme -I~/deneme/d -O -inline -m32
> $ ./deneme
>
> import std.stdio;
> import std.string;
> import std.array;
>
> void main()
> {
> auto myFile = "some.tmp";
> scope(exit) writeln(format("removing %s", myFile));
>
> writeln("myFile.ptr ", myFile.ptr);
>
> void manipulateElement(E)(ref E e)
> {
> size_t local;
> // Playing with pointers (BUG HERE)
> *(&local + 10) = 4;
> *(&local - 1) = 100;
> writeln(&local - 1);
> writeln("myFile ", &myFile);
> writeln("e ", e.ptr);
> }
>
> void manipulateFileRange(R)(R range)
> {
> for (size_t i = 0; i != range.length; ++i) {
> writeln("&i ", &i);
> writeln("i ", i);
> manipulateElement(range[i]);
> }
> }
>
> manipulateFileRange([ myFile ]);
> }
>
> Note that RangeError below is caused by a bug in the program.
Obviously regardless of whether or not RangeError happened you still
corrupted memory. From there to the point of eventual abort/recovery
anything potentially could happen. Data loss or corruption can happen no
matter what and even way before assert triggers.
> Once that
> happens, we cannot say anything about the state of the program. It may
> be 99% correct but it is still in an invalid state.
>
> Here is the output of the program (arrow and comment are added manually
> by me):
>
> myFile.ptr 806C0C4
> &i FFFCE5DC
> i 0
> FFFCE5DC
> myFile FFFCE608
> e 806C0C4
> &i FFFCE5DC
> i 101
> removing some <-- WRONG FILE! (not "some.tmp")
> core.exception.RangeError at deneme(125887): Range violation
The neat thing about your example is that it doesn't matter if you
choose to unwind or abort right away, or even use or not use asserts!
The program was compromised and could destroy data and wreck havoc in
any one of possible ways that an OS allows it.
Think again - what you look at is a failed or successful exploit of a
program (like buffer overflow overwriting some internal pointers say a
ret address). The assert aborting on something fishy won't help you an
inch here:
a) successful exploit will blow its way past any and all high-level
safeguards once it gets in control. The only things that are true
obstacles to it are anti-stack corruption, some heap protection, ASLR
and related techniques. These operate on "the same" lower level.
b) even unsuccessful exploit corrupts things a level deeper then the
language guarantees or constructs operate. In the end simply returning
from a call could cause segfault (overwritten return address).
What I want to underline here is regardless of assertion policy you get
anything you can imagine by corrupting memory in a certain way.
And assertion failure may or may not indicate corruption but regardless
it happens too late to make any kind of judgment based on that and in
particular what to do next. Claiming that you protect from memory
corruption via assert that calls abort by default is as silly as it gets.
Bottom line what I'd suggest is
a) allow Errors to propagate the usual way as Exceptions with the notion
that these are generally fatal and can be used in nothrow.
b) add more options regarding protection against memory corruption aside
from @safe-D
c) add a hook to runtime that allows people to get "abort on Error
thrown" behavior.
--
Dmitry Olshansky
More information about the Digitalmars-d
mailing list