<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/146579>146579</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[[clang::unsafe_buffer_usage]] Source range in unsafe pointer arithmetic warning doesn't show entire unsafe operation
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
tsepez
</td>
</tr>
</table>
<pre>
Given a file range0.cc:
```
int lookup(int *ptr, unsigned idx) {
return ptr[idx];
}
int* predecrement(int* ptr) {
return --ptr; // not actually useful, only for example
}
```
```
range0.cc:3:10:{3:10-3:13}: warning: unsafe buffer access [-Wunsafe-buffer-usage]
3 | return ptr[idx];
| ^~~
range0.cc:3:10: note: pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions
range0.cc:7:12:{7:12-7:15}: warning: unsafe pointer arithmetic [-Wunsafe-buffer-usage]
7 | return --ptr; // not actually useful, only for example
| ^~~
```
The returned range indicates only the unsafe operand rather than the range of the unsafe operation.
We seek to automate applying the _Pragma("clang unsafe_buffer_usage begin") / _Pragma("clang unsafe_buffer_usage end") form of suppression around the ranges as exactly indicated by the compiler,
and using some macro trickery, i.e.
```
#define UNSAFE_BUFFERS(...) \
_Pragma("clang unsafe_buffer_usage begin") \
__VA_ARGS__ \
_Pragma("clang unsafe_buffer_usage end")
int lookup(int *ptr, unsigned idx) {
return UNSAFE_BUFFERS(ptr)[idx];
}
int* predecrement2(int* ptr) {
return --UNSAFE_BUFFERS(ptr); // not actually useful, only for example
}
```
The ptr[idx] looks unusual but does suppress the error. The --ptr case, however gives
```
range1.cc:12:27: warning: unsafe pointer arithmetic [-Wunsafe-buffer-usage]
12 | return --UNSAFE_BUFFERS(ptr); // not actually useful, only for example
| ^~~
```
The returned range should cover the entire unsafe operation, not the unsafe argument allowing us to write
```
int lookup(int *ptr, unsigned idx) {
return UNSAFE_BUFFERS(ptr[idx]);
}
int* predecrement(int* ptr) {
return UNSAFE_BUFFERS(--ptr); // not actually useful, only for example
}
```
which compiles cleanly
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0ls1y2zYQx58GuuyIQ4GhKR10oGIrt04nbpqjBgKXJGoQ4OBDinrIs3eWpGXFilsncTkeEyKwu9gfdv-k8F41BnHN8g3Lb2cihta6dfDY49-zva1O6w_qgAYE1EojOGEaTBMpWVaytGQ36fSXlsoE0NY-xJ7xJf1gvOyDY_w9RDNEqUBVXxhfASs2LC0BHIboDNCqfENz-S3LaIoVt_R_cMp4Cb3DCqXDDun38vEpeb_yNp_T82wDAIxvGd-CsQGEDFFofYLosY6admWNPkFtHeAX0fUan-JeZHU5vkw-Y1m5SIlCsRnH8-GWkYushKNwRpmGhtF4USPsY12jAyEleg8s38w_jzPzcWYevWiQEFAyABmw4j0NXqQEwzWtmi6W3339-tJeiQTSvRfew7y-ij73sWnQB2WNh2DBoUR1QJC2QmiFq5CSgotVz0IVFIqPWMbxfLjlL2LprTKBuDgV2g6Dkq9gUzxj8ytn_j2KTxy_qYW0_KPFKSZWYzOAMpWSIqAfnYcWH1OzPTphaF1o0UFohRmmRztbX60loskY6DOCR3ygQxAx2E4EBNH3-kT8yW73uxNNJxhfMs6lFqaZXO1GZLsBGeyxUYZxTo1CbF5rh6aarGrrOtqsj33v0HtlDQhno6mekvEgPCGVQZ_OQCrYjzik7XqlkaSApSURiX4oI9shdEI6C8Ep-YDuRGcEKsEERgzf4OdZhbUyCJ9-uy-3d7vNp-327uM948skSYYEn18sfz-c8E_AOpvu_ix35ccP97vdj7o7Mzxr2U8K5FW-o_L9gGjy_1bNl4K8mZKO3XMpYzDw8BBN9FFo2McAlUV_rrWhfNA56xIAsh4aHaTwSHFbe8QDOmjUAf11wQyluRiFaRAlXrydBi34pBn_E8AnWXq9FPnWRl2BtIdBbqgCg3LXGkMhaScX-iNcE6lQQGhtj9SdcXgDHJ0KeI32jWv5XMgDrl_8ALiKML4d3raUj62S7aOyeZAahdEnlpazap1Vq2wlZrheFPkiW_FsVcza9Wq15wXmRS73hVjWWZZnYs_xZpnfZLISfKbWPOV5WqSLRZFniyKp0kKs5KrIb-qV5BWydyl2QulE60OXWNfMlPcR14t3N3mxmmmxR-2HL7lJlUh98tuZW5PBfB8bz96lWvngn1wEFfT0-bcZjbKSZeV39IzOJ7-FexudxPPL7196aGq0oaUN40WgAj2-VJSz6PS6DaH3tIPhkBoV2rhPpO0Y39KOp9u8d_YvlIHx7UDAM76dIBzW_J8AAAD__135W-c">