Skip to content

global-buffer-overflow on empty strings on windows #62078

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
amykhuang opened this issue Apr 11, 2023 · 1 comment
Open

global-buffer-overflow on empty strings on windows #62078

amykhuang opened this issue Apr 11, 2023 · 1 comment
Labels
compiler-rt:asan Address sanitizer

Comments

@amykhuang
Copy link
Collaborator

amykhuang commented Apr 11, 2023

I'm seeing ASan crashes on Windows that look like

$ ASAN_OPTIONS=detect_odr_violation=0 ./hello.exe
=================================================================
==16200==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7ff7f15f04e0 at pc 0x7ff7f15a7e68 bp 0x004ff18ff3c0 sp 0x004ff18ff408
READ of size 1 at 0x7ff7f15f04e0 thread T0
    #0 0x7ff7f15a7e67 in __asan_wrap_strlen (C:\src\testing\asan\build\hello.exe+0x140027e67)
    #1 0x7ffde5941699  (C:\Windows\SYSTEM32\ntdll.dll+0x180051699)
    #2 0x7ff7f15ccfbe in __asan_update_allocation_context (C:\src\testing\asan\build\hello.exe+0x14004cfbe)

0x7ff7f15f04e0 is located 15 bytes after global variable '"FLAGS_hello_worl"' defined in 'hello.cc' (0x7ff7f15f04c0) of size 17
  '"FLAGS_hello_worl"' is ascii string 'FLAGS_hello_worl'
0x7ff7f15f04e0 is located 0 bytes inside of global variable '""' defined in 'flag.cc' (0x7ff7f15f04e0) of size 1
  '""' is ascii string ''
SUMMARY: AddressSanitizer: global-buffer-overflow (C:\src\testing\asan\build\hello.exe+0x140027e67) in __asan_wrap_strlen
Shadow bytes around the buggy address:
  0x7ff7f15f0200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff7f15f0280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff7f15f0300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff7f15f0380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff7f15f0400: 00 00 00 00 00 00 f9 f9 00 00 05 f9 f9 f9 f9 f9
=>0x7ff7f15f0480: 00 00 02 f9 f9 f9 f9 f9 00 00 01 f9[f9]f9 f9 f9
  0x7ff7f15f0500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff7f15f0580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff7f15f0600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff7f15f0680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff7f15f0700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==16200==ABORTING

I managed to reduce the code to this:

$ clang -cc1 -triple x86_64-pc-windows-msvc -emit-obj -O0 -fsanitize=address -fno-sanitize-address-use-odr-indicator -o flag.obj -x c++ flag.cc
$ clang -cc1 -triple x86_64-pc-windows-msvc -emit-obj -O0 -fms-extensions -fsanitize=address -fsanitize-address-globals-dead-stripping -fno-sanitize-address-use-odr-indicator -o hello.obj -x c++ hello.cc -isystem "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.33.31629/include" -isystem "C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt" -D_DISABLE_STRING_ANNOTATION
$ llvm-lib hello.obj -OUT:libhello.lib
$ llvm-lib flag.obj -OUT:libflag.lib
$ lld-link -subsystem:console -OUT:hello.exe libhello.lib -wholearchive:libflag.lib -wholearchive:C:/src/llvm-project/build/lib/clang/17/lib/windows/clang_rt.asan-x86_64.lib
$ ASAN_OPTIONS=detect_odr_violation=0 ./hello.exe

where flag.cc is

const char* emptyflag = "";

and hello.cc is

#include <string>

static const char* StringFromEnv(const char* flag) {
  return "";
}

std::string FLAGS_hello = StringFromEnv("FLAGS_hello_worl");

int main() {
  return 0;
}

I also found google/sanitizers#1102 which looks similar.

@amykhuang amykhuang added the compiler-rt:asan Address sanitizer label Apr 11, 2023
@amykhuang
Copy link
Collaborator Author

Update to include that this only happens if linking with lld-link with string tail merging enabled. If you pass /opt:nolldtailmerge, this crash doesn't happen.

goussepi pushed a commit that referenced this issue Dec 7, 2023
… on (#74207)

lld string tail merging interacts badly with ASAN on Windows, as is
reported in #62078.
A similar error was found when building LLVM with
`-DLLVM_USE_SANITIZER=Address`:
```console
[2/2] Building GenVT.inc...
FAILED: include/llvm/CodeGen/GenVT.inc C:/Dev/llvm-project/Build_asan/include/llvm/CodeGen/GenVT.inc
cmd.exe /C "cd /D C:\Dev\llvm-project\Build_asan && C:\Dev\llvm-project\Build_asan\bin\llvm-min-tblgen.exe -gen-vt -I C:/Dev/llvm-project/llvm/include/llvm/CodeGen -IC:/Dev/llvm-project/Build_asan/include -IC:/Dev/llvm-project/llvm/include C:/Dev/llvm-project/llvm/include/llvm/CodeGen/ValueTypes.td --write-if-changed -o include/llvm/CodeGen/GenVT.inc -d include/llvm/CodeGen/GenVT.inc.d"       
=================================================================
==31944==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7ff6cff80d20 at pc 0x7ff6cfcc7378 bp 0x00e8bcb8e990 sp 0x00e8bcb8e9d8
READ of size 1 at 0x7ff6cff80d20 thread T0
    #0 0x7ff6cfcc7377 in strlen (C:\Dev\llvm-project\Build_asan\bin\llvm-min-tblgen.exe+0x1400a7377)
    #1 0x7ff6cfde50c2 in operator delete(void *, unsigned __int64) (C:\Dev\llvm-project\Build_asan\bin\llvm-min-tblgen.exe+0x1401c50c2)
    #2 0x7ff6cfdd75ef in operator delete(void *, unsigned __int64) (C:\Dev\llvm-project\Build_asan\bin\llvm-min-tblgen.exe+0x1401b75ef)
    #3 0x7ff6cfde59f9 in operator delete(void *, unsigned __int64) (C:\Dev\llvm-project\Build_asan\bin\llvm-min-tblgen.exe+0x1401c59f9)
    #4 0x7ff6cff03f6c in operator delete(void *, unsigned __int64) (C:\Dev\llvm-project\Build_asan\bin\llvm-min-tblgen.exe+0x1402e3f6c)
    #5 0x7ff6cfefbcbc in operator delete(void *, unsigned __int64) (C:\Dev\llvm-project\Build_asan\bin\llvm-min-tblgen.exe+0x1402dbcbc)
    #6 0x7ffb7f247343  (C:\WINDOWS\System32\KERNEL32.DLL+0x180017343)
    #7 0x7ffb800826b0  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x1800526b0)

0x7ff6cff80d20 is located 31 bytes after global variable '"#error \"ArgKind is not defined\"\n"...' defined in 'C:\Dev\llvm-project\llvm\utils\TableGen\IntrinsicEmitter.cpp' (0x7ff6cff80ce0) of size 33
  '"#error \"ArgKind is not defined\"\n"...' is ascii string '#error "ArgKind is not defined"
'
0x7ff6cff80d20 is located 0 bytes inside of global variable '""' defined in 'C:\Dev\llvm-project\llvm\utils\TableGen\IntrinsicEmitter.cpp' (0x7ff6cff80d20) of size 1
  '""' is ascii string ''
SUMMARY: AddressSanitizer: global-buffer-overflow (C:\Dev\llvm-project\Build_asan\bin\llvm-min-tblgen.exe+0x1400a7377) in strlen
Shadow bytes around the buggy address:
  0x7ff6cff80a80: 01 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 01 f9 f9 f9
  0x7ff6cff80b00: f9 f9 f9 f9 00 00 00 00 00 00 00 00 01 f9 f9 f9
  0x7ff6cff80b80: f9 f9 f9 f9 00 00 00 00 01 f9 f9 f9 f9 f9 f9 f9
  0x7ff6cff80c00: 00 00 00 00 01 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x7ff6cff80c80: 00 00 00 00 01 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
=>0x7ff6cff80d00: 01 f9 f9 f9[f9]f9 f9 f9 00 00 00 00 00 00 00 00
  0x7ff6cff80d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff6cff80e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff6cff80e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff6cff80f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7ff6cff80f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==31944==ABORTING
```
This is reproducible with the 17.0.3 release:
```console
$ clang-cl --version
clang version 17.0.3
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin
$ cmake -S llvm -B Build -G Ninja -DLLVM_USE_SANITIZER=Address -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_BUILD_TYPE=Release
$ cd Build
$ ninja all
```
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
compiler-rt:asan Address sanitizer
Projects
None yet
Development

No branches or pull requests

1 participant