Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

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

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
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-rt:asan Address sanitizer
Projects
None yet
Development

No branches or pull requests

1 participant