From 6e38072addd556e3894284b5bd040ac64fffa72e Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Fri, 11 Oct 2013 00:45:24 -0700 Subject: [PATCH] Wrap sprintf()/snprintf() macros to prevent expansion errors. Previously, FORTIFY_SOURCE used single macros to define these standard functions for use with clang. This can cause conflicts with other macros used to call these functions, particularly when those macros expand the number of arguments to the function. This change wraps our macro definitions, so that expansion properly takes place for programmer arguments first. Change-Id: I55929b1fd2a643b9d14a17631c4bcab3b0b712cf --- libc/include/stdio.h | 6 ++++-- tests/fortify_test.cpp | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/libc/include/stdio.h b/libc/include/stdio.h index 23fc9448d..a13cfeac6 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -469,7 +469,8 @@ int vsprintf(char *dest, const char *format, __va_list ap) } #if defined(__clang__) -#define snprintf(dest, size, ...) __builtin___snprintf_chk(dest, size, 0, __bos(dest), __VA_ARGS__) +#define __wrap_snprintf(dest, size, ...) __builtin___snprintf_chk(dest, size, 0, __bos(dest), __VA_ARGS__) +#define snprintf(...) __wrap_snprintf(__VA_ARGS__) #else __BIONIC_FORTIFY_INLINE __printflike(3, 4) @@ -481,7 +482,8 @@ int snprintf(char *dest, size_t size, const char *format, ...) #endif #if defined(__clang__) -#define sprintf(dest, ...) __builtin___sprintf_chk(dest, 0, __bos(dest), __VA_ARGS__) +#define __wrap_sprintf(dest, ...) __builtin___sprintf_chk(dest, 0, __bos(dest), __VA_ARGS__) +#define sprintf(...) __wrap_sprintf(__VA_ARGS__) #else __BIONIC_FORTIFY_INLINE __printflike(2, 3) diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp index b42c6b781..408991ef7 100644 --- a/tests/fortify_test.cpp +++ b/tests/fortify_test.cpp @@ -825,3 +825,21 @@ TEST(TEST_NAME, memcpy_chk_max_int_size) { ASSERT_EQ('8', buf[8]); ASSERT_EQ('\0', buf[9]); } + +// Verify that macro expansion is done properly for sprintf/snprintf (which +// are defined as macros in stdio.h under clang). +#define CONTENTS "macro expansion" +#define BUF_AND_SIZE(A) A, sizeof(A) +#define BUF_AND_CONTENTS(A) A, CONTENTS +#define BUF_AND_SIZE_AND_CONTENTS(A) A, sizeof(A), CONTENTS +TEST(TEST_NAME, s_n_printf_macro_expansion) { + char buf[BUFSIZ]; + snprintf(BUF_AND_SIZE(buf), CONTENTS); + EXPECT_STREQ(CONTENTS, buf); + + snprintf(BUF_AND_SIZE_AND_CONTENTS(buf)); + EXPECT_STREQ(CONTENTS, buf); + + sprintf(BUF_AND_CONTENTS(buf)); + EXPECT_STREQ(CONTENTS, buf); +} -- 2.11.0