OSDN Git Service

Wrap sprintf()/snprintf() macros to prevent expansion errors.
authorStephen Hines <srhines@google.com>
Fri, 11 Oct 2013 07:45:24 +0000 (00:45 -0700)
committerStephen Hines <srhines@google.com>
Fri, 11 Oct 2013 19:14:49 +0000 (12:14 -0700)
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
tests/fortify_test.cpp

index 23fc944..a13cfea 100644 (file)
@@ -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)
index b42c6b7..408991e 100644 (file)
@@ -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);
+}