Close #18596: Support address sanity checking in clang/GCC

This patch appropriately marks known false alarms in the
small object allocator when address sanity checking is
enabled (patch contributed by Dhiru Kholia).
diff --git a/Misc/ACKS b/Misc/ACKS
index cb823d1..5b7b630 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -650,6 +650,7 @@
 Magnus Kessler
 Lawrence Kesteloot
 Vivek Khera
+Dhiru Kholia
 Mads Kiilerich
 Jason Killen
 Jan Kim
diff --git a/Misc/NEWS b/Misc/NEWS
index ae8631f..449d915 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -94,6 +94,13 @@
 - Issue #17003: Unified the size argument names in the io module with common
   practice.
 
+Build
+-----
+
+- Issue #18596: Support the use of address sanity checking in recent versions
+  of clang and GCC by appropriately marking known false alarms in the small
+  object allocator. Patch contributed by Dhiru Kholia.
+
 Tools/Demos
 -----------
 
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index 4437bf9..f7b3e49 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -12,6 +12,24 @@
 static void _PyMem_DebugCheckAddress(char api_id, const void *p);
 #endif
 
+#if defined(__has_feature)  /* Clang */
+ #if __has_feature(address_sanitizer)  /* is ASAN enabled? */
+  #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \
+        __attribute__((no_address_safety_analysis)) \
+        __attribute__ ((noinline))
+ #else
+  #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
+ #endif
+#else
+ #if defined(__SANITIZE_ADDRESS__)  /* GCC 4.8.x, is ASAN enabled? */
+  #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \
+        __attribute__((no_address_safety_analysis)) \
+        __attribute__ ((noinline))
+ #else
+  #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
+ #endif
+#endif
+
 #ifdef WITH_PYMALLOC
 
 #ifdef MS_WINDOWS
@@ -1300,6 +1318,7 @@
 
 /* free */
 
+ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
 static void
 _PyObject_Free(void *ctx, void *p)
 {
@@ -1528,6 +1547,7 @@
  * return a non-NULL result.
  */
 
+ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS
 static void *
 _PyObject_Realloc(void *ctx, void *p, size_t nbytes)
 {