#include "pyport.h"
#include "pymacro.h"
+/* A convenient way for code to know if clang's memory sanitizer is enabled. */
+#if defined(__has_feature)
+# if __has_feature(memory_sanitizer)
+# if !defined(MEMORY_SANITIZER)
+# define MEMORY_SANITIZER
+# endif
+# endif
+#endif
+
#include "pyatomic.h"
/* Debug-mode build with pymalloc implies PYMALLOC_DEBUG.
--- /dev/null
+The interpreter and extension modules have had annotations added so that
+they work properly under clang's Memory Sanitizer. A new configure flag
+--with-memory-sanitizer has been added to make test builds of this nature
+easier to perform.
#include <alloca.h>
#endif
+#ifdef MEMORY_SANITIZER
+#include <sanitizer/msan_interface.h>
+#endif
+
#if defined(_DEBUG) || defined(__MINGW32__)
/* Don't use structured exception handling on Windows if this is defined.
MingW, AFAIK, doesn't support it.
rtype = _ctypes_get_ffi_type(restype);
resbuf = alloca(max(rtype->size, sizeof(ffi_arg)));
+#ifdef MEMORY_SANITIZER
+ /* ffi_call actually initializes resbuf, but from asm, which
+ * MemorySanitizer can't detect. Avoid false positives from MSan. */
+ if (resbuf != NULL) {
+ __msan_unpoison(resbuf, max(rtype->size, sizeof(ffi_arg)));
+ }
+#endif
avalues = (void **)alloca(sizeof(void *) * argcount);
atypes = (ffi_type **)alloca(sizeof(ffi_type *) * argcount);
if (!resbuf || !avalues || !atypes) {
#include <dirent.h>
#endif
+#ifdef MEMORY_SANITIZER
+# include <sanitizer/msan_interface.h>
+#endif
+
#if defined(__ANDROID__) && __ANDROID_API__ < 21 && !defined(SYS_getdents64)
# include <sys/linux-syscalls.h>
# define SYS_getdents64 __NR_getdents64
sizeof(buffer))) > 0) {
struct linux_dirent64 *entry;
int offset;
+#ifdef MEMORY_SANITIZER
+ __msan_unpoison(buffer, bytes);
+#endif
for (offset = 0; offset < bytes; offset += entry->d_reclen) {
int fd;
entry = (struct linux_dirent64 *)(buffer + offset);
#ifdef HAVE_SIGALTSTACK
if (stack.ss_sp != NULL) {
/* Fetch the current alt stack */
- stack_t current_stack;
+ stack_t current_stack = {};
if (sigaltstack(NULL, ¤t_stack) == 0) {
if (current_stack.ss_sp == stack.ss_sp) {
/* The current alt stack is the one that we installed.
# endif
#endif
+#ifdef MEMORY_SANITIZER
+# include <sanitizer/msan_interface.h>
+#endif
+
#ifdef Py_DEBUG
int _Py_HashSecret_Initialized = 0;
#else
else {
n = syscall(SYS_getrandom, dest, n, flags);
}
+# ifdef MEMORY_SANITIZER
+ if (n > 0) {
+ __msan_unpoison(dest, n);
+ }
+# endif
#endif
if (n < 0) {
/* inline assembly for getting and setting the 387 FPU control word on
gcc/x86 */
-
+#ifdef MEMORY_SANITIZER
+__attribute__((no_sanitize_memory))
+#endif
unsigned short _Py_get_387controlword(void) {
unsigned short cw;
__asm__ __volatile__ ("fnstcw %0" : "=m" (cw));
with_lto
with_hash_algorithm
with_address_sanitizer
+with_memory_sanitizer
+with_undefined_behavior_sanitizer
with_libs
with_system_expat
with_system_ffi
--with-hash-algorithm=[fnv|siphash24]
select hash algorithm
--with-address-sanitizer
- enable AddressSanitizer
+ enable AddressSanitizer (asan)
+ --with-memory-sanitizer enable MemorySanitizer (msan)
+ --with-undefined-behavior-sanitizer
+ enable UndefinedBehaviorSanitizer (ubsan)
--with-libs='lib1 ...' link against additional libs
--with-system-expat build pyexpat module using an installed expat
library
$as_echo "$withval" >&6; }
BASECFLAGS="-fsanitize=address -fno-omit-frame-pointer $BASECFLAGS"
LDFLAGS="-fsanitize=address $LDFLAGS"
+# ASan works by controlling memory allocation, our own malloc interferes.
+with_pymalloc="no"
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-memory-sanitizer" >&5
+$as_echo_n "checking for --with-memory-sanitizer... " >&6; }
+
+# Check whether --with-memory_sanitizer was given.
+if test "${with_memory_sanitizer+set}" = set; then :
+ withval=$with_memory_sanitizer;
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $withval" >&5
+$as_echo "$withval" >&6; }
+BASECFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer $BASECFLAGS"
+LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 $LDFLAGS"
+# MSan works by controlling memory allocation, our own malloc interferes.
+with_pymalloc="no"
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-undefined-behavior-sanitizer" >&5
+$as_echo_n "checking for --with-undefined-behavior-sanitizer... " >&6; }
+
+# Check whether --with-undefined_behavior_sanitizer was given.
+if test "${with_undefined_behavior_sanitizer+set}" = set; then :
+ withval=$with_undefined_behavior_sanitizer;
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $withval" >&5
+$as_echo "$withval" >&6; }
+BASECFLAGS="-fsanitize=undefined $BASECFLAGS"
+LDFLAGS="-fsanitize=undefined $LDFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
AC_MSG_CHECKING(for --with-address-sanitizer)
AC_ARG_WITH(address_sanitizer,
AS_HELP_STRING([--with-address-sanitizer],
- [enable AddressSanitizer]),
+ [enable AddressSanitizer (asan)]),
[
AC_MSG_RESULT($withval)
BASECFLAGS="-fsanitize=address -fno-omit-frame-pointer $BASECFLAGS"
LDFLAGS="-fsanitize=address $LDFLAGS"
+# ASan works by controlling memory allocation, our own malloc interferes.
+with_pymalloc="no"
+],
+[AC_MSG_RESULT(no)])
+
+AC_MSG_CHECKING(for --with-memory-sanitizer)
+AC_ARG_WITH(memory_sanitizer,
+ AS_HELP_STRING([--with-memory-sanitizer],
+ [enable MemorySanitizer (msan)]),
+[
+AC_MSG_RESULT($withval)
+BASECFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer $BASECFLAGS"
+LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins=2 $LDFLAGS"
+# MSan works by controlling memory allocation, our own malloc interferes.
+with_pymalloc="no"
+],
+[AC_MSG_RESULT(no)])
+
+AC_MSG_CHECKING(for --with-undefined-behavior-sanitizer)
+AC_ARG_WITH(undefined_behavior_sanitizer,
+ AS_HELP_STRING([--with-undefined-behavior-sanitizer],
+ [enable UndefinedBehaviorSanitizer (ubsan)]),
+[
+AC_MSG_RESULT($withval)
+BASECFLAGS="-fsanitize=undefined $BASECFLAGS"
+LDFLAGS="-fsanitize=undefined $LDFLAGS"
],
[AC_MSG_RESULT(no)])