[PATCH] D60047: [CaptureTracking] Don't let comparisons against null escape inbounds pointers

Sanjoy Das via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun May 5 23:09:22 PDT 2019


sanjoy added a comment.

In D60047#1491414 <https://reviews.llvm.org/D60047#1491414>, @jdoerfert wrote:

> Should we interpret your comment as "the reasoning seems sound", or did you only want to point out the special case which I discuss below?


You should interpret it as a drive by comment. :)  I'm fine if you've thought about the case I suggest and are convinced that this change is sound nevertheless.

>> @sanjoy wrote:
>>  However, this example is kind of iffy because in general the `deref_or_null` attribute is not valid since `p` in `main` could have been something other than `-4`.  But *if* the execution has `p` == `-4` then the attribute is well defined.
> 
> I thought about this case, though I didn't spell it out explicitly in my earlier comment (the part: //as the addition "with infinitely precise signed arithmetic" would not overflow//).
> 
> Let me start by stating that I interpret pointers as unsigned values which, under certain conditions, are allowed to overflow. (Maybe that is in itself a problem in my thinking.)
>  So for me `p` is not `-4` but always some positive value, probably `2^N - 1 - 4` where `N` is the pointer bit-width. If that is acceptable, then the inbounds wording in the lang ref
>  prevents the problem you describe. Any addition with a positive value, e.g., the one you choose `(2^N - 1 - 4) + 4`, cannot be `null` without an overflow and inbounds prohibits this overflow.

I'm not sure if inbounds play into this, and I also noticed my example has typos and also is needlessly confusing; corrected example below:

  int** global_ptr;
  
  void unknown_func();
  
  void foo(int32* /*deref_or_null(4)*/ ptr) {
    if (ptr == null) {
      int32* ptr_leaked = (int32*)(intptr_t)-4;
      *global_ptr = ptr_leaked;
    }
  }
  
  void bar() {
    int32* p = new int32;
    // p happens to numerically be -4 == 2^64-4
    int32* p_with_offset = p + 1; // non-inbounds GEP, evaluates to null
    foo(p_with_offset);
  
    // p has been escaped and we can't DCE the first store:
    *p = 10;
    unknown_func();
    *p = 20;
  }

Now lets say we're only looking at `foo`.  I think the current code will conclude that `foo` does not capture `ptr` (we're comparing a `deref_or_null` pointer against `null`) and we will (lets assume) mark `ptr` as `nocapture` which I believe is incorrect, modulo the iffy bit I mentioned before.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60047/new/

https://reviews.llvm.org/D60047





More information about the llvm-commits mailing list