Bug 77396

Summary: address sanitizer crashes if all static global variables are optimized
Product: gcc Reporter: ead <noone>
Component: sanitizerAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: daniel.kruegler, dodji, dvyukov, jakub, kcc, webrown.cpp
Priority: P3    
Version: 6.1.0   
Target Milestone: 6.3   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2016-08-30 00:00:00
Attachments: gcc7-pr77396.patch

Description ead 2016-08-28 12:23:48 UTC
Following stackoverflow discussion: http://stackoverflow.com/questions/39081183/errors-with-g-5-and-6-when-using-address-sanitizer-and-additional-asan-flags-f/39152524#39152524

Compiling 

static int data = 0; 
static int dummy = data; 
int main() { }

with g++ -O2 -fsanitizer=address and running the executable with ASAN_OPTIONS=verbosity=0:strict_string_checks=true:detect_odr_violation=2:check_initialization_order=true:detect_stack_use_after_return=true:strict_init_order=true ./a.out

leads since g++5 to an executable for which the sanitizer crashes during the run. 

The problem is that `data` and `dummy` get optimized together with __asan_register_globals(), but __asan_before_dynamic_init is still called.
Comment 1 Jakub Jelinek 2016-08-30 11:41:52 UTC
Created attachment 39517 [details]
gcc7-pr77396.patch

Untested partial fix for the compiler side.  It should fix the common case when this happens, but it is still possible that something from the file scope ctors isn't optimized away, yet no global vars are referenced, like:
// PR sanitizer/77396
// { dg-do run }
// { dg-additional-options "-O2" }
// { dg-set-target-env-var ASAN_OPTIONS "check_initialization_order=true" }

struct S { S () { asm volatile ("" : : : "memory"); } };
static S c;

int
main ()
{
  return 0;
}

and in that case it will still fail.  I'm afraid it is too hard to fix this inside of GCC, unless we want to emit too ugly code - the __asan_{before,after}_dynamic_call calls need to be in a different function from the function that invokes the globals registration, and the latter is only emitted at the very end, so either we'd need to for -fsanitize=address disable some optimization (e.g. don't remove unused local statics), or force some useless global if there are no other globals but __asan_{before,after}_dynamic_call has been seen.
All in all, IMHO it is better to change __asan_{before,after}_dynamic_call - exit early if the vector is NULL, instead of the assertion.
Comment 2 Jakub Jelinek 2016-09-02 17:12:13 UTC
Author: jakub
Date: Fri Sep  2 17:11:42 2016
New Revision: 239961

URL: https://gcc.gnu.org/viewcvs?rev=239961&root=gcc&view=rev
Log:
	PR sanitizer/77396
	* sanopt.c: Include gimple-ssa.h, tree-phinodes.h and ssa-iterators.h.
	(sanopt_optimize_walker): Optimize away
	__asan_before_dynamic_init (...) followed by
	__asan_after_dynamic_init () without intervening memory loads/stores.
	* ipa-pure-const.c (special_builtin_state): Handle
	BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT and
	BUILT_IN_ASAN_AFTER_DYNAMIC_INIT.

	* decl2.c (do_static_initialization_or_destruction): Only
	call asan_dynamic_init_call if INITP is true.

	* g++.dg/asan/pr77396.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/asan/pr77396.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/decl2.c
    trunk/gcc/ipa-pure-const.c
    trunk/gcc/sanopt.c
    trunk/gcc/testsuite/ChangeLog
Comment 3 Jakub Jelinek 2016-09-05 19:44:29 UTC
Author: jakub
Date: Mon Sep  5 19:43:57 2016
New Revision: 239998

URL: https://gcc.gnu.org/viewcvs?rev=239998&root=gcc&view=rev
Log:
	PR sanitizer/77396
	* asan/asan_globals.cc: Cherry-pick upstream r280657.

	* g++.dg/asan/pr77396-2.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/asan/pr77396-2.C
Modified:
    trunk/gcc/testsuite/ChangeLog
    trunk/libsanitizer/ChangeLog
    trunk/libsanitizer/asan/asan_globals.cc
Comment 4 Jakub Jelinek 2016-09-16 09:34:33 UTC
Author: jakub
Date: Fri Sep 16 09:34:02 2016
New Revision: 240177

URL: https://gcc.gnu.org/viewcvs?rev=240177&root=gcc&view=rev
Log:
	Backported from mainline
	2016-09-05  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/77396
	* asan/asan_globals.cc: Cherry-pick upstream r280657.

	* g++.dg/asan/pr77396-2.C: New test.

	2016-09-02  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/77396
	* g++.dg/asan/pr77396.C: New test.

Added:
    branches/gcc-6-branch/gcc/testsuite/g++.dg/asan/pr77396-2.C
    branches/gcc-6-branch/gcc/testsuite/g++.dg/asan/pr77396.C
Modified:
    branches/gcc-6-branch/gcc/testsuite/ChangeLog
    branches/gcc-6-branch/libsanitizer/ChangeLog
    branches/gcc-6-branch/libsanitizer/asan/asan_globals.cc
Comment 5 Jakub Jelinek 2016-09-16 11:05:19 UTC
Fixed.
Comment 6 Jakub Jelinek 2017-05-30 07:20:22 UTC
Author: jakub
Date: Tue May 30 07:19:49 2017
New Revision: 248603

URL: https://gcc.gnu.org/viewcvs?rev=248603&root=gcc&view=rev
Log:
	Backported from mainline
	2016-09-05  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/77396
	* asan/asan_globals.cc: Cherry-pick upstream r280657.

	2016-09-05  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/77396
	* g++.dg/asan/pr77396-2.C: New test.

	2016-09-02  Jakub Jelinek  <jakub@redhat.com>

	PR sanitizer/77396
	* g++.dg/asan/pr77396.C: New test.

Added:
    branches/gcc-5-branch/gcc/testsuite/g++.dg/asan/pr77396-2.C
    branches/gcc-5-branch/gcc/testsuite/g++.dg/asan/pr77396.C
Modified:
    branches/gcc-5-branch/gcc/testsuite/ChangeLog
    branches/gcc-5-branch/libsanitizer/ChangeLog
    branches/gcc-5-branch/libsanitizer/asan/asan_globals.cc