Add integer_overflow sanitization build option.

Adds the SANITIZE_TARGET=integer_overflow build option to apply signed and
unsigned integer overflow sanitization globally. This implements the
Make side of the build option.

A LOCAL_SANITIZE_BLACKLIST variable is added to allow blacklists to be
defined in make files, mirroring similar functionality provided in Soong.

An additional build option is provided to control whether or not to run
in diagnostics mode, controlled by SANITIZE_TARGET_DIAG. This works the
same way that SANITIZE_TARGET does and currently only supports
'integer_overflow' as an option.

Bug: 30969751
Test: Building with and without the new flags, device boot-up, tested
various permutations of controlling the new flags from build files.

Change-Id: Iacc47e196f21aa1edff5b406bfbc564b5f4e42bd
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 4556fde..1097855 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -216,6 +216,7 @@
 LOCAL_SANITIZE:=
 LOCAL_SANITIZE_DIAG:=
 LOCAL_SANITIZE_RECOVER:=
+LOCAL_SANITIZE_BLACKLIST :=
 LOCAL_SDK_RES_VERSION:=
 LOCAL_SDK_VERSION:=
 LOCAL_SHARED_ANDROID_LIBRARIES:=
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 04aedf4..aaae05b 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -9,6 +9,7 @@
 # modules that haven't set `LOCAL_CLANG := false` and device modules that
 # have set `LOCAL_CLANG := true`.
 my_global_sanitize :=
+my_global_sanitize_diag :=
 ifeq ($(my_clang),true)
   ifdef LOCAL_IS_HOST_MODULE
     my_global_sanitize := $(strip $(SANITIZE_HOST))
@@ -17,18 +18,23 @@
     my_global_sanitize := $(subst true,address,$(my_global_sanitize))
   else
     my_global_sanitize := $(strip $(SANITIZE_TARGET))
+    my_global_sanitize_diag := $(strip $(SANITIZE_TARGET_DIAG))
   endif
 endif
 
 ifneq ($(my_global_sanitize),)
   my_sanitize := $(my_global_sanitize) $(my_sanitize)
 endif
+ifneq ($(my_global_sanitize_diag),)
+  my_sanitize_diag := $(my_global_sanitize_diag) $(my_sanitize_diag)
+endif
 
 # The sanitizer specified in the product configuration wins over the previous.
 ifneq ($(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG),)
   my_sanitize := $(SANITIZER.$(TARGET_PRODUCT).$(LOCAL_MODULE).CONFIG)
   ifeq ($(my_sanitize),never)
     my_sanitize :=
+    my_sanitize_diag :=
   endif
 endif
 
@@ -37,6 +43,7 @@
   SANITIZE_TARGET_ARCH ?= $(TARGET_ARCH) $(TARGET_2ND_ARCH)
   ifeq ($(filter $(SANITIZE_TARGET_ARCH),$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),)
     my_sanitize :=
+    my_sanitize_diag :=
   endif
 endif
 
@@ -47,6 +54,7 @@
     ifneq (,$(filter $(LOCAL_MODULE_OWNER),$(subst :, ,$(SANITIZE_NEVER_BY_OWNER))))
       $(warning Not sanitizing $(LOCAL_MODULE) based on module owner.)
       my_sanitize :=
+      my_sanitize_diag :=
     endif
   endif
 endif
@@ -55,11 +63,13 @@
 ifdef LOCAL_SDK_VERSION
   my_sanitize :=
   my_global_sanitize :=
+  my_sanitize_diag :=
 endif
 
 # Never always wins.
 ifeq ($(LOCAL_SANITIZE),never)
   my_sanitize :=
+  my_sanitize_diag :=
 endif
 
 # If CFI is disabled globally, remove it from my_sanitize.
@@ -86,6 +96,22 @@
   my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag))
 endif
 
+# Support for local sanitize blacklist paths.
+ifneq ($(my_sanitize)$(my_global_sanitize),)
+  ifneq ($(LOCAL_SANITIZE_BLACKLIST),)
+    my_cflags += -fsanitize-blacklist=$(LOCAL_PATH)/$(LOCAL_SANITIZE_BLACKLIST)
+  endif
+endif
+
+# Disable integer_overflow if LOCAL_NOSANITIZE=integer.
+ifneq ($(filter integer_overflow, $(my_global_sanitize) $(my_sanitize)),)
+  ifneq ($(filter integer, $(strip $(LOCAL_NOSANITIZE))),)
+    my_sanitize := $(filter-out integer_overflow,$(my_sanitize))
+    my_sanitize_diag := $(filter-out integer_overflow,$(my_sanitize_diag))
+  endif
+endif
+
+
 my_nosanitize = $(strip $(LOCAL_NOSANITIZE))
 ifneq ($(my_nosanitize),)
   my_sanitize := $(filter-out $(my_nosanitize),$(my_sanitize))
@@ -142,6 +168,37 @@
   my_sanitize := $(filter-out coverage,$(my_sanitize))
 endif
 
+ifneq ($(filter integer_overflow,$(my_sanitize)),)
+  ifneq ($(filter SHARED_LIBRARIES EXECUTABLES,$(LOCAL_MODULE_CLASS)),)
+    ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
+
+      # Respect LOCAL_NOSANITIZE for integer-overflow flags.
+      ifeq ($(filter signed-integer-overflow, $(strip $(LOCAL_NOSANITIZE))),)
+        my_cflags += -fsanitize=signed-integer-overflow
+      endif
+      ifeq ($(filter unsigned-integer-overflow, $(strip $(LOCAL_NOSANITIZE))),)
+        my_cflags += -fsanitize=unsigned-integer-overflow
+      endif
+      my_cflags += -fsanitize-trap=all
+      my_cflags += -ftrap-function=abort
+      my_cflags += $(INTEGER_OVERFLOW_EXTRA_CFLAGS)
+
+      # Check for diagnostics mode (on by default).
+      ifneq ($(filter integer_overflow,$(my_sanitize_diag)),)
+        my_cflags += -fno-sanitize-trap=signed-integer-overflow,unsigned-integer-overflow
+        my_shared_libraries := $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_RUNTIME_LIBRARY) $(my_shared_libraries)
+      endif
+    endif
+  endif
+  my_sanitize := $(filter-out integer_overflow,$(my_sanitize))
+endif
+
+# Makes sure integer_overflow diagnostics is removed from the diagnostics list
+# even if integer_overflow is not set for some reason.
+ifneq ($(filter integer_overflow,$(my_sanitize_diag)),)
+  my_sanitize_diag := $(filter-out integer_overflow,$(my_sanitize_diag))
+endif
+
 ifneq ($(my_sanitize),)
   fsanitize_arg := $(subst $(space),$(comma),$(my_sanitize))
   my_cflags += -fsanitize=$(fsanitize_arg)
diff --git a/core/soong_config.mk b/core/soong_config.mk
index e21083d..472a90c 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -41,6 +41,7 @@
 	echo '    "Allow_missing_dependencies": $(if $(ALLOW_MISSING_DEPENDENCIES),true,false),'; \
 	echo '    "SanitizeHost": $(call json_list,$(SANITIZE_HOST)),'; \
 	echo '    "SanitizeDevice": $(call json_list,$(SANITIZE_TARGET)),'; \
+	echo '    "SanitizeDeviceDiag": $(call json_list,$(SANITIZE_TARGET_DIAG)),'; \
 	echo '    "SanitizeDeviceArch": $(call json_list,$(SANITIZE_TARGET_ARCH)),'; \
 	echo '    "HostStaticBinaries": $(if $(strip $(BUILD_HOST_static)),true,false),'; \
 	echo '    "Binder32bit": $(if $(BINDER32BIT),true,false),'; \