checkedint call removal

Artur Skawina via Digitalmars-d digitalmars-d at puremagic.com
Sat Aug 2 04:12:27 PDT 2014


On 08/02/14 05:34, Andrew Godfrey via Digitalmars-d wrote:
> Suppose I call some logging function which has a faulty assertion in it. What about Walter's position prevents that assertion's effects from escaping the logging function and infecting my code?

Nothing. Walter _wants_ the assumptions to not be contained inside
the assert expression.

> I know cross-module optimization is hard hence this may be unlikely, but still it shows something missing.

Like I said in my very first post about this proposal -- this is
*not* a theoretical issue. It's not some abstract problem that might
surface once a sufficiently smart compiler arrives. It affects code
*right now*. Fortunately, compilers are not using Walter's assert
definition. But that's not because doing it would be 'hard', the
support for these kind of optimization is there. Look:

ass1.d:
---------------------------------------------------------------------
   static import gcc.attribute;
   enum inline = gcc.attribute.attribute("forceinline");

   @inline void assert_()(bool c) {
      import gcc.builtins;
      assert(c);
      if (!c)                         // *1
         __builtin_unreachable();     // *1
   }

   extern (C) void alog(int level, char* msg) {
      assert_(level<10);
      //...
   }

   extern (C) int cf();
   void main() { if (!cf()) assert(0); }
---------------------------------------------------------------------

ass2.c:
---------------------------------------------------------------------
   void alog(int level, char* msg);

   volatile int g = 10;

   int cf() {
      int a = /* an expression that might return 10 at RT */g;

      alog(a, "blah");

      return a==10;
   }
---------------------------------------------------------------------

Compile this with "gdc -O3 ass1.d ass2.c -o ass -flto -frelease" and
this program will fail because the assert triggers. Now, either remove
the lines in the `assert_` function marked with `*1` (it's gcc-speak
for 'assume'), or fix the assert condition -- now the program will
succeed.
The point here is that a simple typo, an off-by-one error, an "<" instead
of "<=", etc, in the assert condition gives you undefined behavior. The
program can then do absolutely everything, return a wrong result, crash
or execute `rm -rv /`. 
In this case gdc compiles it to just:

0000000000402970 <_Dmain>:
  402970:       48 83 ec 08             sub    $0x8,%rsp
  402974:       8b 05 26 ad 25 00       mov    0x25ad26(%rip),%eax        # 65d6a0 <g>
  40297a:       e8 91 f1 ff ff          callq  401b10 <abort at plt>

_`assume` is extremely dangerous_. Redefining `assert` to include `assume`
would result in D's `assert` being banned from the whole code base, if 'D'
even would be consider a 'sane' enough language to use...

artur



More information about the Digitalmars-d mailing list