]> Savannah Git Hosting - gnulib.git/commitdiff
vasnprintf: Don't use %n on modern, ISO C 99 compliant platforms.
authorBruno Haible <bruno@clisp.org>
Sun, 4 Oct 2020 13:59:26 +0000 (15:59 +0200)
committerBruno Haible <bruno@clisp.org>
Sun, 4 Oct 2020 15:39:07 +0000 (17:39 +0200)
Suggested by Jeremie Courreges-Anglas <jca@wxcvbn.org> in
<https://lists.gnu.org/archive/html/bug-gnulib/2020-10/msg00010.html>.

* m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF): Define
HAVE_SNPRINTF_TRUNCATION_C99.
* lib/vasnprintf.c (VASNPRINTF): Don't use %n if
HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99.

ChangeLog
lib/vasnprintf.c
m4/vasnprintf.m4

index 7b528a73dbaa349dae4a7bfe48750b90836badbf..b7f3762362101d4313e7891cc1a4976201c1d150 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2020-10-04  Bruno Haible  <bruno@clisp.org>
+
+       vasnprintf: Don't use %n on modern, ISO C 99 compliant platforms.
+       Suggested by Jeremie Courreges-Anglas <jca@wxcvbn.org> in
+       <https://lists.gnu.org/archive/html/bug-gnulib/2020-10/msg00010.html>.
+       * m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF): Define
+       HAVE_SNPRINTF_TRUNCATION_C99.
+       * lib/vasnprintf.c (VASNPRINTF): Don't use %n if
+       HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99.
+
 2020-10-03  Paul Eggert  <eggert@cs.ucla.edu>
 
        c-stack: streamline Solaris configuration
index 7f75139560778244a5a33075bb4840ddf5de86c1..b232d1462503fd1da785d7e2866906cee9acb72e 100644 (file)
@@ -5117,39 +5117,32 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 #endif
                   *fbp = dp->conversion;
 #if USE_SNPRINTF
-# if ! (((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3))        \
-         && !defined __UCLIBC__)                                            \
-        || (defined __APPLE__ && defined __MACH__)                          \
-        || defined __ANDROID__                                              \
-        || (defined _WIN32 && ! defined __CYGWIN__))
-                fbp[1] = '%';
-                fbp[2] = 'n';
-                fbp[3] = '\0';
-# else
-                /* On glibc2 systems from glibc >= 2.3 - probably also older
-                   ones - we know that snprintf's return value conforms to
-                   ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and
-                   gl_SNPRINTF_TRUNCATION_C99 pass.
-                   Therefore we can avoid using %n in this situation.
-                   On glibc2 systems from 2004-10-18 or newer, the use of %n
-                   in format strings in writable memory may crash the program
-                   (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
-                   in this situation.  */
-                /* On Mac OS X 10.3 or newer, we know that snprintf's return
-                   value conforms to ISO C 99: the tests gl_SNPRINTF_RETVAL_C99
-                   and gl_SNPRINTF_TRUNCATION_C99 pass.
-                   Therefore we can avoid using %n in this situation.
-                   On Mac OS X 10.13 or newer, the use of %n in format strings
-                   in writable memory by default crashes the program, so we
-                   should avoid it in this situation.  */
-                /* On Android, we know that snprintf's return value conforms to
-                   ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and
-                   gl_SNPRINTF_TRUNCATION_C99 pass.
-                   Therefore we can avoid using %n in this situation.
-                   Starting on 2018-03-07, the use of %n in format strings
-                   produces a fatal error (see
-                   <https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336>),
-                   so we should avoid it.  */
+# if ((HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99)            \
+      || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3))       \
+          && !defined __UCLIBC__)                                           \
+      || (defined __APPLE__ && defined __MACH__)                            \
+      || defined __ANDROID__                                                \
+      || (defined _WIN32 && ! defined __CYGWIN__))
+                /* On systems where we know that snprintf's return value
+                   conforms to ISO C 99 (HAVE_SNPRINTF_RETVAL_C99) and that
+                   snprintf always produces NUL-terminated strings
+                   (HAVE_SNPRINTF_TRUNCATION_C99), it is possible to avoid
+                   using %n.  And it is desirable to do so, because more and
+                   more platforms no longer support %n, for "security reasons".
+                   In particular, the following platforms:
+                     - On glibc2 systems from 2004-10-18 or newer, the use of
+                       %n in format strings in writable memory may crash the
+                       program (if compiled with _FORTIFY_SOURCE=2).
+                     - On Mac OS X 10.13 or newer, the use of %n in format
+                       strings in writable memory by default crashes the
+                       program.
+                     - On Android, starting on 2018-03-07, the use of %n in
+                       format strings produces a fatal error (see
+                       <https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336>).
+                   On these platforms, HAVE_SNPRINTF_RETVAL_C99 and
+                   HAVE_SNPRINTF_TRUNCATION_C99 are 1. We have listed them
+                   explicitly in the condition above, in case of cross-
+                   compilation (just to be sure).  */
                 /* On native Windows systems (such as mingw), we can avoid using
                    %n because:
                      - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
@@ -5166,6 +5159,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                      <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-printf-count-output>
                    So we should avoid %n in this situation.  */
                 fbp[1] = '\0';
+# else           /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */
+                fbp[1] = '%';
+                fbp[2] = 'n';
+                fbp[3] = '\0';
 # endif
 #else
                 fbp[1] = '\0';
index 45670618423c2203121d8dae31ece5bd7d1e81a0..43f070e6302486b0bf10bb409fbfa7c31b4eb610 100644 (file)
@@ -1,4 +1,4 @@
-# vasnprintf.m4 serial 37
+# vasnprintf.m4 serial 38
 dnl Copyright (C) 2002-2004, 2006-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -74,6 +74,16 @@ AC_DEFUN_ONCE([gl_PREREQ_VASNPRINTF],
          if the buffer had been large enough.])
       ;;
   esac
+  dnl Additionally, the use of %n can be eliminated by assuming that snprintf
+  dnl always produces NUL-terminated strings (no truncation).
+  AC_REQUIRE([gl_SNPRINTF_TRUNCATION_C99])
+  case "$gl_cv_func_snprintf_truncation_c99" in
+    *yes)
+      AC_DEFINE([HAVE_SNPRINTF_TRUNCATION_C99], [1],
+        [Define if the string produced by the snprintf function is always NUL
+         terminated.])
+      ;;
+  esac
 ])
 
 # Extra prerequisites of lib/vasnprintf.c for supporting 'long double'