[asan] [test] The testcase invalid-pointer-pairs-compare-errors.cpp is brittle
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The testcase invalid-pointer-pairs-compare-errors.cpp, which essentially does this, is brittle:
```c++
int foo(char *p, char *q) {
return p > q;
}
char global1[100] = {}, global2[100] = {};
char __attribute__((used)) smallest_global[5] = {};
char small_global[7] = {};
char __attribute__((used)) little_global[10] = {};
char __attribute__((used)) medium_global[4000] = {};
char large_global[5000] = {};
char __attribute__((used)) largest_global[6000] = {};
int main() {
char *p = &large_global[0];
// CHECK: ERROR: AddressSanitizer: invalid-pointer-pair
// CHECK: #{{[0-9]+ .*}} in main {{.*}}invalid-pointer-pairs-compare-errors.cpp:[[@LINE+1]]
foo(p - 1, p);
}
```
This test normally passes on mingw-w64. However, if the mingw-w64 runtime has been built with `-ffunction-sections -fdata-sections`, this particular bit of the test fails. The reason for this lies in how these globals are laid out in memory.
Normally, these globals are laid out in memory like this (output from `-Wl,-Map,map.txt`):
```
Address Size Align Out In Symbol
[...]
000073c0 000000a0 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-1936ae.o:(.bss$global1)
000073c0 00000000 0 global1
00007460 000000a0 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-1936ae.o:(.bss$global2)
00007460 00000000 0 global2
00007500 00001880 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-1936ae.o:(.bss$large_global)
00007500 00000000 0 large_global
00008d80 00001d40 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-1936ae.o:(.bss$largest_global)
00008d80 00000000 0 largest_global
0000aac0 00000020 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-1936ae.o:(.bss$little_global)
0000aac0 00000000 0 little_global
0000aae0 00001380 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-1936ae.o:(.bss$medium_global)
0000aae0 00000000 0 medium_global
0000be60 00000020 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-1936ae.o:(.bss$small_global)
0000be60 00000000 0 small_global
0000be80 00000020 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-1936ae.o:(.bss$smallest_global)
0000be80 00000000 0 smallest_global
```
These globals are in individual section chunks like `.bss$large_global` etc. The linker sorts these alphabetically.
If the mingw-w64 runtime has been built with `-ffunction-sections -fdata-sections`, then global variables from that runtime also are placed in similar `.bss$` section chunks - ending up with a link map that looks like this:
```
Address Size Align Out In Symbol
[...]
000073c0 000000a0 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-ecb0ea.o:(.bss$global1)
000073c0 00000000 0 global1
00007460 000000a0 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-ecb0ea.o:(.bss$global2)
00007460 00000000 0 global2
00007500 00000001 4 lib64_libmingw32_a-gccmain.o:(.bss$initialized)
00007500 00000000 0 initialized
00007520 00001880 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-ecb0ea.o:(.bss$large_global)
00007520 00000000 0 large_global
00008da0 00001d40 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-ecb0ea.o:(.bss$largest_global)
00008da0 00000000 0 largest_global
0000aae0 00000020 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-ecb0ea.o:(.bss$little_global)
0000aae0 00000000 0 little_global
0000ab00 00001380 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-ecb0ea.o:(.bss$medium_global)
0000ab00 00000000 0 medium_global
0000be80 00000020 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-ecb0ea.o:(.bss$small_global)
0000be80 00000000 0 small_global
0000bea0 00000020 32 C:/Users/ADMINI~1/AppData/Local/Temp/2/invalid-pointer-pairs-compare-errors-ecb0ea.o:(.bss$smallest_global)
0000bea0 00000000 0 smallest_global
```
Here, a section chunk `.bss$initialized` has been laid out between `global2` and `large_global`.
When the test executable creates the pointer `large_global-1`, this previously used to point to memory that belonged to the chunk covered by `global2` (which is instrumented by asan). But now this pointer instead falls into the chunk that belongs to `initialized`, which isn't instrumented by asan. Therefore, the asan runtime doesn't warn about the pointer comparison, and the test fails in this build configuration (as it doesn't produce the errors that were expected here).
Contributor guide
Research direction
Start by reading invalid-pointer-pairs-compare-errors.cpp and reproducing the test with a mingw-w64 runtime built using -ffunction-sections -fdata-sections. Trace how the test depends on global section ordering, then make its invalid-pointer-pair check stable across the layouts described in the issue; done means the test produces the expected ASan diagnostics in both configurations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100