diff options
| author | Paul Eggert | 2011-05-04 00:19:21 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-05-04 00:19:21 -0700 |
| commit | c378da0b47eb8c26fc8da4d89e128ee3c73537de (patch) | |
| tree | 69780b09fd68c972f69c1414d48c84cb24a075fa | |
| parent | 288b08c747644d42c1636c2b469f8c34836ccd35 (diff) | |
| download | emacs-c378da0b47eb8c26fc8da4d89e128ee3c73537de.tar.gz emacs-c378da0b47eb8c26fc8da4d89e128ee3c73537de.zip | |
Use C99's va_copy to avoid undefined behavior on x86-64 GNU/Linux.
| -rw-r--r-- | ChangeLog | 4 | ||||
| -rw-r--r-- | Makefile.in | 2 | ||||
| -rw-r--r-- | lib/gnulib.mk | 29 | ||||
| -rw-r--r-- | lib/stdarg.in.h | 36 | ||||
| -rw-r--r-- | m4/gl-comp.m4 | 9 | ||||
| -rw-r--r-- | m4/stdarg.m4 | 78 | ||||
| -rw-r--r-- | src/ChangeLog | 3 | ||||
| -rw-r--r-- | src/eval.c | 5 |
8 files changed, 163 insertions, 3 deletions
| @@ -1,5 +1,9 @@ | |||
| 1 | 2011-05-04 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2011-05-04 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Use C99's va_copy to avoid undefined behavior on x86-64 GNU/Linux. | ||
| 4 | * Makefile.in (GNULIB_MODULES): Add stdarg, for va_copy. | ||
| 5 | * lib/stdarg.in.h, m4/stdarg.m4: New files, from gnulib. | ||
| 6 | |||
| 3 | * Makefile.in (GNULIB_TOOL_FLAG): Add --conditional-dependencies. | 7 | * Makefile.in (GNULIB_TOOL_FLAG): Add --conditional-dependencies. |
| 4 | This new gnulib-tool option saves 'configure' the trouble of | 8 | This new gnulib-tool option saves 'configure' the trouble of |
| 5 | checking for strtoull when strtoumax exists. | 9 | checking for strtoull when strtoumax exists. |
diff --git a/Makefile.in b/Makefile.in index 180f7e5be16..ba2926d2853 100644 --- a/Makefile.in +++ b/Makefile.in | |||
| @@ -333,7 +333,7 @@ DOS_gnulib_comp.m4 = gl-comp.m4 | |||
| 333 | GNULIB_MODULES = \ | 333 | GNULIB_MODULES = \ |
| 334 | careadlinkat crypto/md5 dtoastr filemode getloadavg getopt-gnu \ | 334 | careadlinkat crypto/md5 dtoastr filemode getloadavg getopt-gnu \ |
| 335 | ignore-value intprops lstat mktime readlink \ | 335 | ignore-value intprops lstat mktime readlink \ |
| 336 | socklen stdio strftime strtoumax symlink sys_stat | 336 | socklen stdarg stdio strftime strtoumax symlink sys_stat |
| 337 | GNULIB_TOOL_FLAGS = \ | 337 | GNULIB_TOOL_FLAGS = \ |
| 338 | --conditional-dependencies --import --no-changelog --no-vc-files \ | 338 | --conditional-dependencies --import --no-changelog --no-vc-files \ |
| 339 | --makefile-name=gnulib.mk | 339 | --makefile-name=gnulib.mk |
diff --git a/lib/gnulib.mk b/lib/gnulib.mk index faf89aaa0e6..1466e430a4c 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | # the same distribution terms as the rest of that program. | 9 | # the same distribution terms as the rest of that program. |
| 10 | # | 10 | # |
| 11 | # Generated by gnulib-tool. | 11 | # Generated by gnulib-tool. |
| 12 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files careadlinkat crypto/md5 dtoastr filemode getloadavg getopt-gnu ignore-value intprops lstat mktime readlink socklen stdio strftime strtoumax symlink sys_stat | 12 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files careadlinkat crypto/md5 dtoastr filemode getloadavg getopt-gnu ignore-value intprops lstat mktime readlink socklen stdarg stdio strftime strtoumax symlink sys_stat |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | MOSTLYCLEANFILES += core *.stackdump | 15 | MOSTLYCLEANFILES += core *.stackdump |
| @@ -258,6 +258,33 @@ EXTRA_libgnu_a_SOURCES += stat.c | |||
| 258 | 258 | ||
| 259 | ## end gnulib module stat | 259 | ## end gnulib module stat |
| 260 | 260 | ||
| 261 | ## begin gnulib module stdarg | ||
| 262 | |||
| 263 | BUILT_SOURCES += $(STDARG_H) | ||
| 264 | |||
| 265 | # We need the following in order to create <stdarg.h> when the system | ||
| 266 | # doesn't have one that works with the given compiler. | ||
| 267 | if GL_GENERATE_STDARG_H | ||
| 268 | stdarg.h: stdarg.in.h $(top_builddir)/config.status | ||
| 269 | $(AM_V_GEN)rm -f $@-t $@ && \ | ||
| 270 | { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ | ||
| 271 | sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ | ||
| 272 | -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ | ||
| 273 | -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ | ||
| 274 | -e 's|@''NEXT_STDARG_H''@|$(NEXT_STDARG_H)|g' \ | ||
| 275 | < $(srcdir)/stdarg.in.h; \ | ||
| 276 | } > $@-t && \ | ||
| 277 | mv $@-t $@ | ||
| 278 | else | ||
| 279 | stdarg.h: $(top_builddir)/config.status | ||
| 280 | rm -f $@ | ||
| 281 | endif | ||
| 282 | MOSTLYCLEANFILES += stdarg.h stdarg.h-t | ||
| 283 | |||
| 284 | EXTRA_DIST += stdarg.in.h | ||
| 285 | |||
| 286 | ## end gnulib module stdarg | ||
| 287 | |||
| 261 | ## begin gnulib module stdbool | 288 | ## begin gnulib module stdbool |
| 262 | 289 | ||
| 263 | BUILT_SOURCES += $(STDBOOL_H) | 290 | BUILT_SOURCES += $(STDBOOL_H) |
diff --git a/lib/stdarg.in.h b/lib/stdarg.in.h new file mode 100644 index 00000000000..4469d54e4f4 --- /dev/null +++ b/lib/stdarg.in.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | /* Substitute for and wrapper around <stdarg.h>. | ||
| 2 | Copyright (C) 2008-2011 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 3, or (at your option) | ||
| 7 | any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software Foundation, | ||
| 16 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
| 17 | |||
| 18 | #ifndef _GL_STDARG_H | ||
| 19 | |||
| 20 | #if __GNUC__ >= 3 | ||
| 21 | @PRAGMA_SYSTEM_HEADER@ | ||
| 22 | #endif | ||
| 23 | @PRAGMA_COLUMNS@ | ||
| 24 | |||
| 25 | /* The include_next requires a split double-inclusion guard. */ | ||
| 26 | #@INCLUDE_NEXT@ @NEXT_STDARG_H@ | ||
| 27 | |||
| 28 | #ifndef _GL_STDARG_H | ||
| 29 | #define _GL_STDARG_H | ||
| 30 | |||
| 31 | #ifndef va_copy | ||
| 32 | # define va_copy(a,b) ((a) = (b)) | ||
| 33 | #endif | ||
| 34 | |||
| 35 | #endif /* _GL_STDARG_H */ | ||
| 36 | #endif /* _GL_STDARG_H */ | ||
diff --git a/m4/gl-comp.m4 b/m4/gl-comp.m4 index 4338f2036b1..87d7616f8bb 100644 --- a/m4/gl-comp.m4 +++ b/m4/gl-comp.m4 | |||
| @@ -51,6 +51,12 @@ AC_DEFUN([gl_EARLY], | |||
| 51 | # Code from module socklen: | 51 | # Code from module socklen: |
| 52 | # Code from module ssize_t: | 52 | # Code from module ssize_t: |
| 53 | # Code from module stat: | 53 | # Code from module stat: |
| 54 | # Code from module stdarg: | ||
| 55 | dnl Some compilers (e.g., AIX 5.3 cc) need to be in c99 mode | ||
| 56 | dnl for the builtin va_copy to work. With Autoconf 2.60 or later, | ||
| 57 | dnl AC_PROG_CC_STDC arranges for this. With older Autoconf AC_PROG_CC_STDC | ||
| 58 | dnl shouldn't hurt, though installers are on their own to set c99 mode. | ||
| 59 | AC_REQUIRE([AC_PROG_CC_STDC]) | ||
| 54 | # Code from module stdbool: | 60 | # Code from module stdbool: |
| 55 | # Code from module stddef: | 61 | # Code from module stddef: |
| 56 | # Code from module stdint: | 62 | # Code from module stdint: |
| @@ -104,6 +110,7 @@ gl_FUNC_READLINK | |||
| 104 | gl_UNISTD_MODULE_INDICATOR([readlink]) | 110 | gl_UNISTD_MODULE_INDICATOR([readlink]) |
| 105 | gl_TYPE_SOCKLEN_T | 111 | gl_TYPE_SOCKLEN_T |
| 106 | gt_TYPE_SSIZE_T | 112 | gt_TYPE_SSIZE_T |
| 113 | gl_STDARG_H | ||
| 107 | AM_STDBOOL_H | 114 | AM_STDBOOL_H |
| 108 | gl_STDDEF_H | 115 | gl_STDDEF_H |
| 109 | gl_STDINT_H | 116 | gl_STDINT_H |
| @@ -358,6 +365,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 358 | lib/mktime.c | 365 | lib/mktime.c |
| 359 | lib/readlink.c | 366 | lib/readlink.c |
| 360 | lib/stat.c | 367 | lib/stat.c |
| 368 | lib/stdarg.in.h | ||
| 361 | lib/stdbool.in.h | 369 | lib/stdbool.in.h |
| 362 | lib/stddef.in.h | 370 | lib/stddef.in.h |
| 363 | lib/stdint.in.h | 371 | lib/stdint.in.h |
| @@ -395,6 +403,7 @@ AC_DEFUN([gl_FILE_LIST], [ | |||
| 395 | m4/ssize_t.m4 | 403 | m4/ssize_t.m4 |
| 396 | m4/st_dm_mode.m4 | 404 | m4/st_dm_mode.m4 |
| 397 | m4/stat.m4 | 405 | m4/stat.m4 |
| 406 | m4/stdarg.m4 | ||
| 398 | m4/stdbool.m4 | 407 | m4/stdbool.m4 |
| 399 | m4/stddef_h.m4 | 408 | m4/stddef_h.m4 |
| 400 | m4/stdint.m4 | 409 | m4/stdint.m4 |
diff --git a/m4/stdarg.m4 b/m4/stdarg.m4 new file mode 100644 index 00000000000..5705de9ecaa --- /dev/null +++ b/m4/stdarg.m4 | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | # stdarg.m4 serial 6 | ||
| 2 | dnl Copyright (C) 2006, 2008-2011 Free Software Foundation, Inc. | ||
| 3 | dnl This file is free software; the Free Software Foundation | ||
| 4 | dnl gives unlimited permission to copy and/or distribute it, | ||
| 5 | dnl with or without modifications, as long as this notice is preserved. | ||
| 6 | |||
| 7 | dnl From Bruno Haible. | ||
| 8 | dnl Provide a working va_copy in combination with <stdarg.h>. | ||
| 9 | |||
| 10 | AC_DEFUN([gl_STDARG_H], | ||
| 11 | [ | ||
| 12 | STDARG_H='' | ||
| 13 | NEXT_STDARG_H='<stdarg.h>' | ||
| 14 | AC_MSG_CHECKING([for va_copy]) | ||
| 15 | AC_CACHE_VAL([gl_cv_func_va_copy], [ | ||
| 16 | AC_COMPILE_IFELSE( | ||
| 17 | [AC_LANG_PROGRAM( | ||
| 18 | [[#include <stdarg.h>]], | ||
| 19 | [[ | ||
| 20 | #ifndef va_copy | ||
| 21 | void (*func) (va_list, va_list) = va_copy; | ||
| 22 | #endif | ||
| 23 | ]])], | ||
| 24 | [gl_cv_func_va_copy=yes], | ||
| 25 | [gl_cv_func_va_copy=no])]) | ||
| 26 | AC_MSG_RESULT([$gl_cv_func_va_copy]) | ||
| 27 | if test $gl_cv_func_va_copy = no; then | ||
| 28 | dnl Provide a substitute. | ||
| 29 | dnl Usually a simple definition in <config.h> is enough. Not so on AIX 5 | ||
| 30 | dnl with some versions of the /usr/vac/bin/cc compiler. It has an <stdarg.h> | ||
| 31 | dnl which does '#undef va_copy', leading to a missing va_copy symbol. For | ||
| 32 | dnl this platform, we use an <stdarg.h> substitute. But we cannot use this | ||
| 33 | dnl approach on other platforms, because <stdarg.h> often defines only | ||
| 34 | dnl preprocessor macros and gl_ABSOLUTE_HEADER, gl_CHECK_NEXT_HEADERS do | ||
| 35 | dnl not work in this situation. | ||
| 36 | AC_EGREP_CPP([vaccine], | ||
| 37 | [#if defined _AIX && !defined __GNUC__ | ||
| 38 | AIX vaccine | ||
| 39 | #endif | ||
| 40 | ], [gl_aixcc=yes], [gl_aixcc=no]) | ||
| 41 | if test $gl_aixcc = yes; then | ||
| 42 | dnl Provide a substitute <stdarg.h> file. | ||
| 43 | STDARG_H=stdarg.h | ||
| 44 | gl_NEXT_HEADERS([stdarg.h]) | ||
| 45 | dnl Fallback for the case when <stdarg.h> contains only macro definitions. | ||
| 46 | if test "$gl_cv_next_stdarg_h" = '""'; then | ||
| 47 | gl_cv_next_stdarg_h='"///usr/include/stdarg.h"' | ||
| 48 | NEXT_STDARG_H="$gl_cv_next_stdarg_h" | ||
| 49 | fi | ||
| 50 | else | ||
| 51 | dnl Provide a substitute in <config.h>, either __va_copy or as a simple | ||
| 52 | dnl assignment. | ||
| 53 | gl_CACHE_VAL_SILENT([gl_cv_func___va_copy], [ | ||
| 54 | AC_COMPILE_IFELSE( | ||
| 55 | [AC_LANG_PROGRAM( | ||
| 56 | [[#include <stdarg.h>]], | ||
| 57 | [[ | ||
| 58 | #ifndef __va_copy | ||
| 59 | error, bail out | ||
| 60 | #endif | ||
| 61 | ]])], | ||
| 62 | [gl_cv_func___va_copy=yes], | ||
| 63 | [gl_cv_func___va_copy=no])]) | ||
| 64 | if test $gl_cv_func___va_copy = yes; then | ||
| 65 | AC_DEFINE([va_copy], [__va_copy], | ||
| 66 | [Define as a macro for copying va_list variables.]) | ||
| 67 | else | ||
| 68 | AH_VERBATIM([gl_VA_COPY], [/* A replacement for va_copy, if needed. */ | ||
| 69 | #define gl_va_copy(a,b) ((a) = (b))]) | ||
| 70 | AC_DEFINE([va_copy], [gl_va_copy], | ||
| 71 | [Define as a macro for copying va_list variables.]) | ||
| 72 | fi | ||
| 73 | fi | ||
| 74 | fi | ||
| 75 | AC_SUBST([STDARG_H]) | ||
| 76 | AM_CONDITIONAL([GL_GENERATE_STDARG_H], [test -n "$STDARG_H"]) | ||
| 77 | AC_SUBST([NEXT_STDARG_H]) | ||
| 78 | ]) | ||
diff --git a/src/ChangeLog b/src/ChangeLog index 9fac265ae48..a1aa19e6f2e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,8 @@ | |||
| 1 | 2011-05-04 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2011-05-04 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Use C99's va_copy to avoid undefined behavior on x86-64 GNU/Linux. | ||
| 4 | * eval.c (verror): doprnt a copy of ap, not the original. (Bug#8545) | ||
| 5 | |||
| 3 | * eval.c (verror): OK to create a string of up to MOST_POSITIVE_FIXNUM | 6 | * eval.c (verror): OK to create a string of up to MOST_POSITIVE_FIXNUM |
| 4 | bytes. | 7 | bytes. |
| 5 | 8 | ||
diff --git a/src/eval.c b/src/eval.c index 90ef02ef37b..6b4182cb319 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -2002,7 +2002,10 @@ verror (const char *m, va_list ap) | |||
| 2002 | 2002 | ||
| 2003 | while (1) | 2003 | while (1) |
| 2004 | { | 2004 | { |
| 2005 | used = doprnt (buffer, size, m, m + mlen, ap); | 2005 | va_list ap_copy; |
| 2006 | va_copy (ap_copy, ap); | ||
| 2007 | used = doprnt (buffer, size, m, m + mlen, ap_copy); | ||
| 2008 | va_end (ap_copy); | ||
| 2006 | 2009 | ||
| 2007 | /* Note: the -1 below is because `doprnt' returns the number of bytes | 2010 | /* Note: the -1 below is because `doprnt' returns the number of bytes |
| 2008 | excluding the terminating null byte, and it always terminates with a | 2011 | excluding the terminating null byte, and it always terminates with a |