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