Following up on this, http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/21348/focus=21349
Here's a complete patch: >From a099f49dedfea850ef78fa5e987b95edd5ebc58d Mon Sep 17 00:00:00 2001 From: Jim Meyering <meyer...@redhat.com> Date: Thu, 14 Oct 2010 11:38:14 +0200 Subject: [PATCH] inttostr.h: add compile-time buffer overrun checks * lib/inttostr.h: Add a wrapper for each function that can detect use of an undersized buffer. Now that there are #define's, make this header idempotent. --- ChangeLog | 7 +++++++ lib/inttostr.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 0 deletions(-) diff --git a/ChangeLog b/ChangeLog index 42d0fef..6707c6e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-10-16 Jim Meyering <meyer...@redhat.com> + + inttostr.h: add compile-time buffer overrun checks + * lib/inttostr.h: Add a wrapper for each function that can detect + use of an undersized buffer. + Now that there are #define's, make this header idempotent. + 2010-10-15 Bruno Haible <br...@clisp.org> tests: Make them compile with TinyCC. diff --git a/lib/inttostr.h b/lib/inttostr.h index 4f74968..9c1e41b 100644 --- a/lib/inttostr.h +++ b/lib/inttostr.h @@ -17,10 +17,14 @@ /* Written by Paul Eggert */ +#ifndef _GL_INTTOSTR_H +# define _GL_INTTOSTR_H + #include <stdint.h> #include <sys/types.h> #include "intprops.h" +#include "verify.h" #ifndef __GNUC_PREREQ # if defined __GNUC__ && defined __GNUC_MINOR__ @@ -44,3 +48,44 @@ 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__; + +#ifndef inttype + +/* When it is possible to determine at compile-time (given an S for which + sizeof (S) is different from sizeof (void *)), ensure that each use of + one of these functions provides a buffer that is known to be large enough. + This won't save you if you mistakenly declare char S[4] (on a 32-bit system) + or char S[8] (on others), but will induce compile failure on a 32-bit system + if you mistakenly declare these: + size_t v; char S[INT_BUFSIZE_BOUND (v)]; + and then try to use umaxtostr (n, S). + It fails because INT_BUFSIZE_BOUND(size_t) is too small to hold the + largest uintmax_t value on 32-bit systems. */ + +# define imaxtostr(n, s) \ + ((void) verify_true (sizeof (s) == sizeof (void *) \ + || INT_BUFSIZE_BOUND (intmax_t) <= sizeof (s)), \ + (imaxtostr) (n, s)) + +# define inttostr(n, s) \ + ((void) verify_true (sizeof (s) == sizeof (void *) \ + || INT_BUFSIZE_BOUND (int) <= sizeof (s)), \ + (inttostr) (n, s)) + +# define offtostr(n, s) \ + ((void) verify_true (sizeof (s) == sizeof (void *) \ + || INT_BUFSIZE_BOUND (off_t) <= sizeof (s)), \ + (offtostr) (n, s)) + +# define uinttostr(n, s) \ + ((void) verify_true (sizeof (s) == sizeof (void *) \ + || INT_BUFSIZE_BOUND (unsigned int) <= sizeof (s)), \ + (uinttostr) (n, s)) + +# define umaxtostr(n, s) \ + ((void) verify_true (sizeof (s) == sizeof (void *) \ + || INT_BUFSIZE_BOUND (uintmax_t) <= sizeof (s)), \ + (umaxtostr) (n, s)) +#endif + +#endif -- 1.7.3.1.526.g2ee4