[llvm-dev] Possible soundness issue with available_externally (split from "RFC: Add guard intrinsics")

Xinliang David Li via llvm-dev llvm-dev at lists.llvm.org
Mon Feb 29 10:38:00 PST 2016


ok thanks.  A more reduced test case can show different behavior between O2
and O0.

Say we have

unsigned maybe_divide (unsigned *ptr) {
   int flag = false;
   unsigned val = 500/ptr[0];
   if (flag)
       return val;
   return (unsigned)(intptr_t)ptr);
}

int main() {
   unsigned g = 0;
    return maybe_divide(&g);
}


At O2, it runs fine, but at O0 it core dumps.

what is the right behavior?

David


On Sat, Feb 27, 2016 at 5:21 PM, Sanjoy Das <sanjoy at playingwithpointers.com>
wrote:

> On Sat, Feb 27, 2016 at 4:21 PM, Xinliang David Li <xinliangli at gmail.com>
> wrote:
> > So in this case, ptr[0] = 10 is propagated into one copy of maybe_devide
> (in
> > source a), and ptr[0]=10 in caller_a is DSEed ?
>
> `ptr[0] = 10` is not really propagated anywhere.  What happens is that
> `source-a` 's copy of `maybe_divide` gets optimized to a `ret
> (unsigned) ptr` (after inlining in the body of `always_false`)[1], so
> it is able to DSE the store `ptr[0] = 10`.  But `source-b` s copy of
> `maybe_divide` still has the load and the division (since it does not
> have access to `always_false` 's body), so if `caller_a` ends up
> calling that implementation of `maybe_divide`, we get a `SIGFPE`.
>
> [1]: For reference, after inlining `always_false`, the `maybe_divide`
>   becomes
>
>     unsigned maybe_divide(unsigned *ptr) {
>       unsigned val = 500 / ptr[0]; // dead value
>       if (false)
>         return val;
>       return (unsigned)((intptr_t)ptr);
>     }
>
> -- Sanjoy
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160229/5fcc38c5/attachment.html>


More information about the llvm-dev mailing list