#include #include #include "intprops.h" #include "verify.h" #ifndef __GNUC_PREREQ # if defined __GNUC__ && defined __GNUC_MINOR__ # define __GNUC_PREREQ(maj, min) \ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) # else # define __GNUC_PREREQ(maj, min) 0 # endif #endif #if __GNUC_PREREQ (3,4) # undef __attribute_warn_unused_result__ # define __attribute_warn_unused_result__ \ __attribute__ ((__warn_unused_result__)) #else # define __attribute_warn_unused_result__ /* empty */ #endif char *imaxtostr (intmax_t, char *) __attribute_warn_unused_result__; char *inttostr (int, char *) __attribute_warn_unused_result__; char *offtostr (off_t, char *) __attribute_warn_unused_result__; char *uinttostr (unsigned int, char *) __attribute_warn_unused_result__; char *umaxtostr (uintmax_t, char *) __attribute_warn_unused_result__; char *inttostr_chk (int, char *, size_t) __attribute_warn_unused_result__; /* The value of this macro is determined by gl_ASM_SYMBOL_PREFIX. */ #define USER_LABEL_PREFIX #define _GL_STRINGIFY(s) _GL_STRINGIFY1 (s) #define _GL_STRINGIFY1(s) #s #define ASM_SYMBOL_PREFIX _GL_STRINGIFY (USER_LABEL_PREFIX) /* __attribute__ __warning__ requires GCC >= 4.3. __builtin_object_size requires GCC >= 4.1. __always_inline__ requires GCC >= 3.2. */ #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && __USE_FORTIFY_LEVEL > 0 /* Compiler determined size of a char* pointer. or char[] array. Works via a GCC built-in for pointers into arrays of constant size, and works via sizeof() for references to arrays of variable length. Punt for pointers to arrays of variable length or unknown length. */ # define _GL_pointed_object_size(s) \ (__builtin_object_size (s, 1) != (size_t)-1 \ ? __builtin_object_size (s, 1) \ : sizeof (s) != sizeof (void *) \ ? sizeof (s) \ : (size_t)-1) # define inttostr(n, s) \ (__extension__ (inttostr_chk_inline (n, s, _GL_pointed_object_size (s)))) extern char *inttostr_chk_warn (int n, char *s, size_t size) __asm__ (ASM_SYMBOL_PREFIX "inttostr_chk"); extern __typeof__ (inttostr_chk_warn) inttostr_chk_warn __attribute__((__warning__ ("inttostr: size of destination buffer too small"))); static inline __attribute__ ((__always_inline__)) char * inttostr_chk_inline (int n, char *s, size_t size) { if (__builtin_constant_p (size)) { if (size != (size_t)-1) { /* buffer size known at compile time. */ if (size >= INT_BUFSIZE_BOUND (int)) return (inttostr) (n, s); else return inttostr_chk_warn (n, s, size); } else /* buffer size unknown. */ return (inttostr) (n, s); } /* buffer size unknown at compile time but known at run time. */ return inttostr_chk (n, s, size); } #endif /* Buffer too small: warning at compile time, and call inttostr_chk. */ static int foo1_size; void foo1 (int n) { char buf[5]; foo1_size = __builtin_object_size (buf, 1); // 5 char *result = inttostr (n, buf); } static int foo2_size; void foo2 (int n) { char buf[5]; foo2_size = __builtin_object_size (&buf[0], 1); // 5 char *result = inttostr (n, &buf[0]); } /* Buffer large enough: no warning, and call inttostr. */ static int foo3_size; void foo3 (int n) { char buf[13]; foo3_size = __builtin_object_size (buf, 1); // 13 char *result = inttostr (n, buf); } static int foo4_size; void foo4 (int n) { char buf[13]; foo4_size = __builtin_object_size (&buf[0], 1); // 13 char *result = inttostr (n, &buf[0]); } /* Buffer size unknown at compile time but known at run time. No warning, but call inttostr_chk. */ static int foo5_size; static int foo5_sizeof; void foo5 (int n) { char buf[11+(n<0)]; foo5_size = __builtin_object_size (buf, 1); // -1 foo5_sizeof = sizeof (buf); // 11+(n<0) char *result = inttostr (n, buf); } /* Buffer size unknown. No warning. Call inttostr. */ static int foo6_size; static int foo6_sizeof; void foo6 (int n) { char buf[11+(n<0)]; foo6_size = __builtin_object_size (&buf[0], 1); // -1 foo6_sizeof = sizeof (&buf[0]); // sizeof (void *) char *result = inttostr (n, &buf[0]); }