<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/132739>132739</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [CaptureTracking] False Negatives in `PointerMayBeCaptured` Due to Missing Underlying Object Backtracking
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          Camsyn
      </td>
    </tr>
</table>

<pre>
    ## Description
`PointerMaybeCaptured`, as its name suggests, is supposed to take an arbitrary pointer and analyze whether it might be captured.
However, the current capture checking in `PointerMayBeCaptured` may produce false negatives by directly tracking the def-use chain of the given pointer without first backtracking to its underlying object. This leads to missed captures when analyzing derived pointers (e.g., GEP results) with their base objects captured.

## Reproducer
Analyze whether `&arr[1]` is captured or not.
```cpp
void foo(char *);
int main() {
  int arr[2] = {0, 0};
  pthread_t t;
  // `arr` is captured through the pointer argument
  foo(arr);
  // Current implementation considers `arr + 1` as non-captured
  arr[1] = 2;
 ...
}
```

## Analysis of Current Usage
Currently, there are TWO different patterns of the pointer argument passed to `PointerMayBeCaptured`.
### Safe Patterns (Majority of Existing Uses)
- **Direct patterns with guaranteed base objects**:
  - `Alloca` instructions
  - Function arguments
  - Return values with `noalias` attributes
  - Pointers processed through `getUnderlyingObject()`

- **These account for uses in**:
  - `InstructionSimplify.cpp`
  - `InstCombineCompares.cpp`
  - `FunctionAttrs.cpp` (with manual object backtracking)
  - `DeadStoreElimination.cpp`
  - `SimplifyCFG.cpp`

### Potentially Problematic Cases
- `ThreadSanitizer.cpp`: Uses pointer operand of Store/Load directly
- `SanitizerBinaryMetadata.cpp`: Processes pointer operand of Store/Load for GWP-San metadata

The FNs of capture relation of load/store addresses might lead to FN in TSan's race detection, observed in this [Godbolt example](https://godbolt.org/z/n67GrxdcE):

## TWO Potential Fixes

1. **Fix of Restriction**: Explicitly or implicitly restrict the pattern of pointer argument of `PointerMayBeCaptured`
   - Explicitly state in API comments that a pointer not from a base object might be mis-analyzed as non-captured.
   - Or add an inner assertion to limit the passed pointer must be a base object.
   > If so, the use cases in `ThreadSanitizer.cpp` and `SanitizerBinaryMetadata.cpp` need to be fixed

2. **Fix of Implementation** (Recommended):
   - Add extra underlying object resolution in the beginning of `PointerMayBeCaptured`:
     ```cpp
     const Value *Obj = getUnderlyingObject(Ptr);
     return analyzeCaptures(Obj);
 ```
   - As most of the usages of `PointerMayBeCaptured` just pass the underlying object pointer to it, this fix would not introduce obvious overhead, but eliminate the FN when the argument pointer is not of underlying object.




</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyEV01v4soS_TXNphRkGgjJgoUTQt5IbyZoknl3-VS2y7gzdrfVXSZhfv1VtW3Ix70zElKC3V1f59SpAkMwe0u0VssbtdxMsOPK-fUtNuFoJ5krjmul50rPYUMh96Zl46xKUnWZ7JyxTP4rHjO6xZY7T4W6TJS-BQxgOIDFhiB0-z0FDvLcBAhd27pABbADxp8EaAF9ZtijP0Lb2wS0BaDF-viL4KUirsiDYWjMvmLICPLB31Ql6X_cCx3Ii32uCPLOe7I8HoG8ovynsXswFt5FffM2amjwCK13RZcTlFgHAkt7ZHOgANkRCuMp5_oI7LE3J74KKi-6ID7QWHBlfLg3B7KnTF4MV65jKI0PDBnmP88WXKxSZwvy9VGeuOyZcp7CU2UC1IRFkEONCVKwIaEgBbFDdeRSQd4cqBg9BlD6iqb7qRTk_m4HnkJXS_2vYzASo_GQYaDBX3hXTvn0iH-noSBeJWn6AY2I9CV6r5Y3M7XcSA3N2RI4D9bxtKdK_8nbViXpwZkCSueUvsor9KB0qvS1mt-oJDWWoUFjlb6ScNVKHgLI496TVssNqPlGXkWmJWq16e8CtFx5wuL_DDw-Unqr9FaClfsfQuTKu24fC3Imnt93DVmOt_so5eYY4Mni7cAy07Q1yQWUxoDc2WCKCEJ0CUrfwEwcYwDr7MXoPNo6Vy_mpAcf02ks22rztnjvkIlgBBOEcmMkPwLuSSXp8L0-Dg3hCdATPP31AIUpS4qHW2Qmb8PI2Y_pQ4thaNJ_75npKSCJ6RFLgt1oV-mrr_jsvOGj-Lh7NYGFrD8CCRNVkl70yKeb2FnniCJH9x16tExUvCNqf0PN01i-C4ktrWuXY4TWBvZdLjiE4f22s_H7Ka_xxXfizls4YN3R4FJdJtZhbTBEuJi9yTqm8cZu7K7Wu5z64gz8UZfJnvjHqY0fYrA9h0_Ijek-VRQIMM9dZxlK56ELFEA4_ym3L-eMHoVopjxOpYmizTdnbl2TGUu3rmnRU_h0ZixDyuzHt4JQzLtB22E9VPidQPU4DTY2hMUjO093tWmMjXT_5GiM8nZ7f373jiU7x2TZYF0fYeddVlODbHK4xRBLHc08xT5-RGvY_CI_mpqnkT4nsrqWvAwKV0KMTOntfx0WJ60ezZ0M3RiL_viVGAtkfGN2N2D6Z9sC2P1fu4tHtNAMhvocnyqC7bfYUePo8VT3suBKqB0WSm-DGAMsCt_76yeaSL302vabTKmnR7RKrwJ4zGXGMEX0pJ9dFsiL2BsLLENCLW_uXZG5moFeUcRItFhfVcxtEDJFudr3R6bO75Xe_lJ6ay9X9_61yO-itKXv1EWk4oQTbM1rREYl6Ww6kHhrXiWn7xTYmyG4gb1w99rWJjcyK52P-jh888PpXnD6dhcrn7THlb8RnUg2uHjrJjAySUXS3RfIXRMbHbhCBjxZt46h9K4BfKso542iMeFi2DiKj2I9HZ0-eIFOVhZjrYQcAvmIMDuQvhiTi_owum66EF288zzYVPM7-FJCcOP6EtcJ7CXh33shLkh_pDZY6jU8IyjNa5w6Kkn1Bxi_vJth_SuRh-_UF7Og4sSSWIa0KIBe2ePn3UVQdnUXaxI5SpDR3lgbj_wW2NE-wIeNIT6TycrwPxFsif4he44z85-Fd8dvRzYA-F7vB4AHr0Hpq4fs-Xzy7bDtEw3QuMDjlOxkxIbfpwHPgrYwoL_yqUAjK-L216NugsADL66ri0hUY3lYRV12MK4L4A7kKxIJuYWsY6BBhSl62X7rl0L5_zzCB0cmRJuu_IdNc-j7-JkU63lxPb_GCa1nq4W-0svr1XJSrRe6XK5Wi2yVZbPF9eVitdC0uEp0UlxeUpbNJmatE71M5noxW8yu9XxazK-yEq9nOsMyowzVIqEGTT2t60MjKjQxIXS0ns31an49qTGjOsSfIFpbeoH4VmnZ9iZ-LZcusm4f1CKpTeBwNsOG6_jbZUDgaRxdyw1s4xb_7bTF_37_33QkkHw1IcQ95VyqnlVw82YyTjpfrz9IrOGqy6a5a5TeSnzDn4vWu56V25hVUHo7pH1Y678DAAD__0SOdBQ">