diff options
6 files changed, 178 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/asan/snprintf-fortify-1.c b/gcc/testsuite/gcc.dg/asan/snprintf-fortify-1.c new file mode 100644 index 00000000000..b5e1a6e5101 --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/snprintf-fortify-1.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-options "-D_FORTIFY_SOURCE=1 -w" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O1" } } */ +/* { dg-shouldfail "asan" } */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +const char * +__asan_default_options () { + return "fast_unwind_on_malloc=false"; +} + +#ifdef __cplusplus +} +#endif + +int main(int argc, char **argv) { + char *short_buffer = (char*)malloc(3); + snprintf (short_buffer, 10, "%s_%s", "hello", "world"); /* BOOM */ + return short_buffer[0]; +} +/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)__snprintf_chk|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ + diff --git a/gcc/testsuite/gcc.dg/asan/sprintf-fortify-1.c b/gcc/testsuite/gcc.dg/asan/sprintf-fortify-1.c new file mode 100644 index 00000000000..86fed28e373 --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/sprintf-fortify-1.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-options "-D_FORTIFY_SOURCE=1 -w" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O1" } } */ +/* { dg-shouldfail "asan" } */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +const char * +__asan_default_options () { + return "fast_unwind_on_malloc=false"; +} + +#ifdef __cplusplus +} +#endif + +int main(int argc, char **argv) { + char *short_buffer = (char*)malloc(3); + sprintf (short_buffer, "%s_%s", "hello", "world"); /* BOOM */ + return short_buffer[0]; +} +/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)__sprintf_chk|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ + diff --git a/gcc/testsuite/gcc.dg/asan/vsnprintf-fortify-1.c b/gcc/testsuite/gcc.dg/asan/vsnprintf-fortify-1.c new file mode 100644 index 00000000000..711c31f84e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/vsnprintf-fortify-1.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-D_FORTIFY_SOURCE=1 -w" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O1" } } */ +/* { dg-shouldfail "asan" } */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +const char * +__asan_default_options () { + return "fast_unwind_on_malloc=false"; +} + +#ifdef __cplusplus +} +#endif + +__attribute__((noinline, noclone)) +char foo (const char *format, ...) { + char *str = (char *) malloc (1); + va_list ap; + va_start (ap, format); + vsnprintf (str, 10, format, ap); + va_end (ap); + return str[1]; +} + +int main(int argc, char **argv) { + return foo ("%s_%s", "hello", "world"); +} +/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)__vsnprintf_chk|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ + diff --git a/gcc/testsuite/gcc.dg/asan/vsprintf-fortify-1.c b/gcc/testsuite/gcc.dg/asan/vsprintf-fortify-1.c new file mode 100644 index 00000000000..d14f38fff75 --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/vsprintf-fortify-1.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-options "-D_FORTIFY_SOURCE=1 -w" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O1" } } */ +/* { dg-shouldfail "asan" } */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +const char * +__asan_default_options () { + return "fast_unwind_on_malloc=false"; +} + +#ifdef __cplusplus +} +#endif + +char foo (const char *format, ...) { + char *str = (char *) malloc (1); + va_list ap; + va_start (ap, format); + vsprintf (str, format, ap); + va_end (ap); + return str[1]; +} + +int main(int argc, char **argv) { + return foo ("%s_%s", "hello", "world"); +} +/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)__vsprintf_chk|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ + diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc index 38390ed9621..d3059f0c2f7 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc +++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc @@ -1331,6 +1331,12 @@ INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format, va_list ap) VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap) +#if SANITIZER_INTERCEPT___PRINTF_CHK +INTERCEPTOR(int, __vsnprintf_chk, char *str, SIZE_T size, int flag, + SIZE_T size_to, const char *format, va_list ap) +VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap) +#endif + #if SANITIZER_INTERCEPT_PRINTF_L INTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc, const char *format, va_list ap) @@ -1344,6 +1350,12 @@ FORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format) INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap) VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap) +#if SANITIZER_INTERCEPT___PRINTF_CHK +INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to, + const char *format, va_list ap) +VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap) +#endif + INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap) VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap) @@ -1372,12 +1384,30 @@ FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format) INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...) FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format) +#if SANITIZER_INTERCEPT___PRINTF_CHK +INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size, + const char *format, ...) +FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format) +#endif + INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT +#if SANITIZER_INTERCEPT___PRINTF_CHK +INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to, + const char *format, ...) // NOLINT +FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) // NOLINT +#endif + INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...) FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format) +#if SANITIZER_INTERCEPT___PRINTF_CHK +INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag, + SIZE_T size_to, const char *format, ...) // NOLINT +FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) // NOLINT +#endif + INTERCEPTOR(int, asprintf, char **strp, const char *format, ...) FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format) @@ -1417,6 +1447,17 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size, #define INIT_PRINTF #endif +#if SANITIZER_INTERCEPT___PRINTF_CHK +#define INIT___PRINTF_CHK \ + COMMON_INTERCEPT_FUNCTION(__sprintf_chk); \ + COMMON_INTERCEPT_FUNCTION(__snprintf_chk); \ + COMMON_INTERCEPT_FUNCTION(__vsprintf_chk); \ + COMMON_INTERCEPT_FUNCTION(__vsnprintf_chk); \ + COMMON_INTERCEPT_FUNCTION(__fprintf_chk); +#else +#define INIT___PRINTF_CHK +#endif + #if SANITIZER_INTERCEPT_PRINTF_L #define INIT_PRINTF_L \ COMMON_INTERCEPT_FUNCTION(snprintf_l); \ @@ -6072,4 +6113,5 @@ static void InitializeCommonInterceptors() { INIT___LXSTAT; INIT___LXSTAT64; // FIXME: add other *stat interceptors. + INIT___PRINTF_CHK; } diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h index 2a886058187..db1668e4773 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h +++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h @@ -116,6 +116,9 @@ # define SANITIZER_INTERCEPT_ISOC99_PRINTF SI_LINUX_NOT_ANDROID #endif +#define SANITIZER_INTERCEPT___PRINTF_CHK \ + (SANITIZER_INTERCEPT_PRINTF && SI_LINUX_NOT_ANDROID) + #define SANITIZER_INTERCEPT_FREXP 1 #define SANITIZER_INTERCEPT_FREXPF_FREXPL SI_NOT_WINDOWS |