From b5ec3a2d5567c1d66831c5511f86c241d80954de Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Tue, 12 Feb 2013 14:29:34 +0000 Subject: [PATCH] [sanitizer] More accurate scanf parsing without GNU extensions. In __isoc99_*scanf we don't have to worry about GNUisms, and can parse %a accurately. Patch by Jakub Jelinek. llvm-svn: 174969 --- .../sanitizer_common/sanitizer_common_interceptors.inc | 16 ++++++++-------- .../sanitizer_common_interceptors_scanf.inc | 12 +++++++----- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 42d8d82..f402f20 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -150,7 +150,7 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, #include "sanitizer_common_interceptors_scanf.inc" -#define VSCANF_INTERCEPTOR_IMPL(vname, ...) \ +#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...) \ { \ void *ctx; \ COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \ @@ -158,29 +158,29 @@ INTERCEPTOR(int, prctl, int option, unsigned long arg2, va_copy(aq, ap); \ int res = REAL(vname)(__VA_ARGS__); \ if (res > 0) \ - scanf_common(ctx, res, format, aq); \ + scanf_common(ctx, res, allowGnuMalloc, format, aq); \ va_end(aq); \ return res; \ } INTERCEPTOR(int, vscanf, const char *format, va_list ap) -VSCANF_INTERCEPTOR_IMPL(vscanf, format, ap) +VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap) INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap) -VSCANF_INTERCEPTOR_IMPL(vsscanf, str, format, ap) +VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap) INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap) -VSCANF_INTERCEPTOR_IMPL(vfscanf, stream, format, ap) +VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap) INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap) -VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, format, ap) +VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap) INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format, va_list ap) -VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, str, format, ap) +VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap) INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap) -VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, stream, format, ap) +VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap) #define SCANF_INTERCEPTOR_IMPL(name, vname, ...) \ { \ diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc index 9ab5ae2..8bb5cd8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_scanf.inc @@ -39,7 +39,8 @@ static bool char_is_one_of(char c, const char *s) { // returned in dir. This function returns the pointer to the first // unprocessed character, or 0 in case of error. // In case of the end-of-string, a pointer to the closing \0 is returned. -static const char *scanf_parse_next(const char *p, ScanfDirective *dir) { +static const char *scanf_parse_next(const char *p, bool allowGnuMalloc, + ScanfDirective *dir) { internal_memset(dir, 0, sizeof(*dir)); dir->argIdx = -1; @@ -121,7 +122,8 @@ static const char *scanf_parse_next(const char *p, ScanfDirective *dir) { // This is unfortunately ambiguous between old GNU extension // of %as, %aS and %a[...] and newer POSIX %a followed by // letters s, S or [. - if (dir->convSpecifier == 'a' && !dir->lengthModifier[0]) { + if (allowGnuMalloc && dir->convSpecifier == 'a' && + !dir->lengthModifier[0]) { if (*p == 's' || *p == 'S') { dir->maybeGnuMalloc = true; ++p; @@ -271,14 +273,14 @@ static int scanf_get_store_size(ScanfDirective *dir) { // Common part of *scanf interceptors. // Process format string and va_list, and report all store ranges. // Stops when "consuming" n_inputs input items. -static void scanf_common(void *ctx, int n_inputs, const char *format, - va_list aq) { +static void scanf_common(void *ctx, int n_inputs, bool allowGnuMalloc, + const char *format, va_list aq) { CHECK_GT(n_inputs, 0); const char *p = format; while (*p && n_inputs) { ScanfDirective dir; - p = scanf_parse_next(p, &dir); + p = scanf_parse_next(p, allowGnuMalloc, &dir); if (!p) break; if (dir.convSpecifier == 0) { -- 2.7.4