<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/127188>127188</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[analyzer] `security.ArrayBound` lacks check for `std::array` or array passed by reference
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
zufuliu
</td>
</tr>
</table>
<pre>
https://godbolt.org/z/aq7fTn8Tj
```c++
int table[256];
int bar1(signed char x) {
const unsigned char y = x;
if (x >= 0) {
return y;
}
return table[y];
}
int bar2(int x) {
if (x >= 0) {
//return x;
}
return table[x];
}
template<typename T, unsigned N>
struct Foo {
T operator[](unsigned i) const {
return items[i];
}
T items[N];
};
int bar3(Foo<int, 256> &foo, int x) {
if (x >= 0) {
//return x;
}
return foo[x];
}
int foo1(int (&tab)[256], signed char x) {
const unsigned char y = x;
if (x >= 0) {
return y;
}
return tab[y];
}
int foo2(int (&tab)[256], int x) {
if (x >= 0) {
//return x;
}
return tab[x];
}
#include <array>
std::array<int, 256> table2;
int foo3(int x) {
if (x >= 0) {
//return x;
}
return table2[x];
}
int foo4(std::array<int, 256> &tab, int x) {
if (x >= 0) {
//return x;
}
return tab[x];
}
```
```console
<source>:7:12: warning: Out of bound access to memory preceding 'table' [clang-analyzer-security.ArrayBound]
7 | return table[y];
| ^~~~~~~~
<source>:4:9: note: Assuming 'x' is < 0
4 | if (x >= 0) {
| ^~~~~~
<source>:4:5: note: Taking false branch
4 | if (x >= 0) {
| ^
<source>:7:12: note: Access of 'table' at negative byte offset
7 | return table[y];
| ^~~~~~~~
<source>:14:12: warning: Out of bound access to memory preceding 'table' [clang-analyzer-security.ArrayBound]
14 | return table[x];
| ^~~~~~~~
<source>:11:9: note: Assuming 'x' is < 0
11 | if (x >= 0) {
| ^~~~~~
<source>:11:5: note: Taking false branch
11 | if (x >= 0) {
| ^
<source>:14:12: note: Access of 'table' at negative byte offset
14 | return table[x];
| ^~~~~~~~
<source>:20:16: warning: Out of bound access to memory preceding the field 'items' [clang-analyzer-security.ArrayBound]
20 | return items[i];
| ^
<source>:26:9: note: Assuming 'x' is < 0
26 | if (x >= 0) {
| ^~~~~~
<source>:26:5: note: Taking false branch
26 | if (x >= 0) {
| ^
<source>:29:12: note: Calling 'Foo::operator[]'
29 | return foo[x];
| ^~~~~~
<source>:20:16: note: Access of the field 'items' at negative byte offset
20 | return items[i];
| ^~~~~~~~
4031 warnings generated.
Suppressed 4028 warnings (4028 in non-user code).
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzEl82S4jYQx5-muXQNZbf8eeBgmOG4OYQXkG0ZvGskIsm7sIc8e0q2-RxgYDabuFyFS8jSr__9V1vixtRLKcQEwimEryPe2pXSk59t1TZ1O8pVuZusrN0YYBnQHGi-VGWuGjtWegk0_wk053_F1UImi6_gZe6OvP4ugKbu9rJaWrQ8bwSEUwojCF-B7dtzrn2gpMMosVhxjVugFCF2PRARCyWNxVaedtkhsFfc9sNgXSFQskVgb67ZO3_fXVrYVkvcDS8gIsSvw9Pw3x5wd8Druxw5CShxjxd8H8-OvXTDRNsHILbvIaxYbxpuBbCZ3W2E5GuBC6DZUZkvjsDLjNVtYXGu1AnGAtVGaG6V7jMNlBzeqx1xr_JV1Wor1gbCaX2AOmdfHHp8OcPuHw7yMaBkrhSwWS2tA3dWYG8IFFVKuYbnxH1YVDf6VUkHtkopf0gtUAIUWZ4DpUez0gx_yZ8PmeQxi942aKUUfRTFb3HvGdw1lYnVsmjaUiCwGdea7_ZGLV1ZYdnQduGLbi3QmYsqpdh_tAjpejADReBK1n38fQY-qfoztNdQ91X4sigraVQjXBObGdXqQnQMWQws8wlYhj-4lrVcusc_Wouqwly1skReFMIYtArXYq30DjdaFKKs5RKB4r5yUYwQTouGy-ULl7zZ_RT6xYii1bXdjTMn1NQN5mj7KGKEeHa7Bg9ixDM8uSB8-7u_3scRAMtSxy6Vq5UZZsa06wFy6wBr43yI3jB6cBj9o6ScUuwRrgOEpwAL_s1NX_HGCMw1l8XqU1ND-HYvbYd4-zSp6iwr3KIUS27r7wLznRWoqsoI-5uS4Af_j5v8o6I3P6hngt6OwH_SR77_L_uoI3jMSJ-Y-6qZTtL2C256KAlPmIk8RxV90kx2JbCqRVO6APp9ypO2Iu-M9u6m6N0quak1RU8ajKJnq8UtPaOHjfXYnHc9Rek7T8140wxxdvtB9w293J3GA0B6WpkuN3J369JdI72393Wf3DX6w8a47omj4QOP-XtvG1wK6bQQ5Ri87M92s9HCGFFi4FFy7AWUdA21RKnkS2uExkKVAigdn37wR-WElSlL-UhM_JilIcUBS0erCSVlKCIqqYooTPOSMYqCmAcJBUEQsXJUT8ij0CM_8D2PhemY8phKzsLYE7mXlwUEnljzuhk3zfe1OxCOamNaMfEp9pNk1PBcNKY7WRJJ8QO7f4HIHTT1xL30krdLA4HX1Maa4zC2tk13JN2vTghfESLv2hqNPGx48c1gsRLFN6yU7nqe780iD5XG7hk3vFMz36EWldBCFmLU6ubymFvbVZuPC7UGmjuw4edlo9VXUVigeReOAZoP8X6f0D8BAAD__-j-NcA">