Use C99's va_copy to avoid undefined behavior on x86-64 GNU/Linux.
This commit is contained in:
parent
288b08c747
commit
c378da0b47
8 changed files with 163 additions and 3 deletions
|
@ -1,5 +1,9 @@
|
|||
2011-05-04 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Use C99's va_copy to avoid undefined behavior on x86-64 GNU/Linux.
|
||||
* Makefile.in (GNULIB_MODULES): Add stdarg, for va_copy.
|
||||
* lib/stdarg.in.h, m4/stdarg.m4: New files, from gnulib.
|
||||
|
||||
* Makefile.in (GNULIB_TOOL_FLAG): Add --conditional-dependencies.
|
||||
This new gnulib-tool option saves 'configure' the trouble of
|
||||
checking for strtoull when strtoumax exists.
|
||||
|
|
|
@ -333,7 +333,7 @@ DOS_gnulib_comp.m4 = gl-comp.m4
|
|||
GNULIB_MODULES = \
|
||||
careadlinkat crypto/md5 dtoastr filemode getloadavg getopt-gnu \
|
||||
ignore-value intprops lstat mktime readlink \
|
||||
socklen stdio strftime strtoumax symlink sys_stat
|
||||
socklen stdarg stdio strftime strtoumax symlink sys_stat
|
||||
GNULIB_TOOL_FLAGS = \
|
||||
--conditional-dependencies --import --no-changelog --no-vc-files \
|
||||
--makefile-name=gnulib.mk
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
# the same distribution terms as the rest of that program.
|
||||
#
|
||||
# Generated by gnulib-tool.
|
||||
# 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
|
||||
# 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
|
||||
|
||||
|
||||
MOSTLYCLEANFILES += core *.stackdump
|
||||
|
@ -258,6 +258,33 @@ EXTRA_libgnu_a_SOURCES += stat.c
|
|||
|
||||
## end gnulib module stat
|
||||
|
||||
## begin gnulib module stdarg
|
||||
|
||||
BUILT_SOURCES += $(STDARG_H)
|
||||
|
||||
# We need the following in order to create <stdarg.h> when the system
|
||||
# doesn't have one that works with the given compiler.
|
||||
if GL_GENERATE_STDARG_H
|
||||
stdarg.h: stdarg.in.h $(top_builddir)/config.status
|
||||
$(AM_V_GEN)rm -f $@-t $@ && \
|
||||
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
|
||||
sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
|
||||
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
|
||||
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
|
||||
-e 's|@''NEXT_STDARG_H''@|$(NEXT_STDARG_H)|g' \
|
||||
< $(srcdir)/stdarg.in.h; \
|
||||
} > $@-t && \
|
||||
mv $@-t $@
|
||||
else
|
||||
stdarg.h: $(top_builddir)/config.status
|
||||
rm -f $@
|
||||
endif
|
||||
MOSTLYCLEANFILES += stdarg.h stdarg.h-t
|
||||
|
||||
EXTRA_DIST += stdarg.in.h
|
||||
|
||||
## end gnulib module stdarg
|
||||
|
||||
## begin gnulib module stdbool
|
||||
|
||||
BUILT_SOURCES += $(STDBOOL_H)
|
||||
|
|
36
lib/stdarg.in.h
Normal file
36
lib/stdarg.in.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* Substitute for and wrapper around <stdarg.h>.
|
||||
Copyright (C) 2008-2011 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef _GL_STDARG_H
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
@PRAGMA_SYSTEM_HEADER@
|
||||
#endif
|
||||
@PRAGMA_COLUMNS@
|
||||
|
||||
/* The include_next requires a split double-inclusion guard. */
|
||||
#@INCLUDE_NEXT@ @NEXT_STDARG_H@
|
||||
|
||||
#ifndef _GL_STDARG_H
|
||||
#define _GL_STDARG_H
|
||||
|
||||
#ifndef va_copy
|
||||
# define va_copy(a,b) ((a) = (b))
|
||||
#endif
|
||||
|
||||
#endif /* _GL_STDARG_H */
|
||||
#endif /* _GL_STDARG_H */
|
|
@ -51,6 +51,12 @@ AC_DEFUN([gl_EARLY],
|
|||
# Code from module socklen:
|
||||
# Code from module ssize_t:
|
||||
# Code from module stat:
|
||||
# Code from module stdarg:
|
||||
dnl Some compilers (e.g., AIX 5.3 cc) need to be in c99 mode
|
||||
dnl for the builtin va_copy to work. With Autoconf 2.60 or later,
|
||||
dnl AC_PROG_CC_STDC arranges for this. With older Autoconf AC_PROG_CC_STDC
|
||||
dnl shouldn't hurt, though installers are on their own to set c99 mode.
|
||||
AC_REQUIRE([AC_PROG_CC_STDC])
|
||||
# Code from module stdbool:
|
||||
# Code from module stddef:
|
||||
# Code from module stdint:
|
||||
|
@ -104,6 +110,7 @@ gl_FUNC_READLINK
|
|||
gl_UNISTD_MODULE_INDICATOR([readlink])
|
||||
gl_TYPE_SOCKLEN_T
|
||||
gt_TYPE_SSIZE_T
|
||||
gl_STDARG_H
|
||||
AM_STDBOOL_H
|
||||
gl_STDDEF_H
|
||||
gl_STDINT_H
|
||||
|
@ -358,6 +365,7 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
lib/mktime.c
|
||||
lib/readlink.c
|
||||
lib/stat.c
|
||||
lib/stdarg.in.h
|
||||
lib/stdbool.in.h
|
||||
lib/stddef.in.h
|
||||
lib/stdint.in.h
|
||||
|
@ -395,6 +403,7 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
m4/ssize_t.m4
|
||||
m4/st_dm_mode.m4
|
||||
m4/stat.m4
|
||||
m4/stdarg.m4
|
||||
m4/stdbool.m4
|
||||
m4/stddef_h.m4
|
||||
m4/stdint.m4
|
||||
|
|
78
m4/stdarg.m4
Normal file
78
m4/stdarg.m4
Normal file
|
@ -0,0 +1,78 @@
|
|||
# stdarg.m4 serial 6
|
||||
dnl Copyright (C) 2006, 2008-2011 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
dnl Provide a working va_copy in combination with <stdarg.h>.
|
||||
|
||||
AC_DEFUN([gl_STDARG_H],
|
||||
[
|
||||
STDARG_H=''
|
||||
NEXT_STDARG_H='<stdarg.h>'
|
||||
AC_MSG_CHECKING([for va_copy])
|
||||
AC_CACHE_VAL([gl_cv_func_va_copy], [
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <stdarg.h>]],
|
||||
[[
|
||||
#ifndef va_copy
|
||||
void (*func) (va_list, va_list) = va_copy;
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_func_va_copy=yes],
|
||||
[gl_cv_func_va_copy=no])])
|
||||
AC_MSG_RESULT([$gl_cv_func_va_copy])
|
||||
if test $gl_cv_func_va_copy = no; then
|
||||
dnl Provide a substitute.
|
||||
dnl Usually a simple definition in <config.h> is enough. Not so on AIX 5
|
||||
dnl with some versions of the /usr/vac/bin/cc compiler. It has an <stdarg.h>
|
||||
dnl which does '#undef va_copy', leading to a missing va_copy symbol. For
|
||||
dnl this platform, we use an <stdarg.h> substitute. But we cannot use this
|
||||
dnl approach on other platforms, because <stdarg.h> often defines only
|
||||
dnl preprocessor macros and gl_ABSOLUTE_HEADER, gl_CHECK_NEXT_HEADERS do
|
||||
dnl not work in this situation.
|
||||
AC_EGREP_CPP([vaccine],
|
||||
[#if defined _AIX && !defined __GNUC__
|
||||
AIX vaccine
|
||||
#endif
|
||||
], [gl_aixcc=yes], [gl_aixcc=no])
|
||||
if test $gl_aixcc = yes; then
|
||||
dnl Provide a substitute <stdarg.h> file.
|
||||
STDARG_H=stdarg.h
|
||||
gl_NEXT_HEADERS([stdarg.h])
|
||||
dnl Fallback for the case when <stdarg.h> contains only macro definitions.
|
||||
if test "$gl_cv_next_stdarg_h" = '""'; then
|
||||
gl_cv_next_stdarg_h='"///usr/include/stdarg.h"'
|
||||
NEXT_STDARG_H="$gl_cv_next_stdarg_h"
|
||||
fi
|
||||
else
|
||||
dnl Provide a substitute in <config.h>, either __va_copy or as a simple
|
||||
dnl assignment.
|
||||
gl_CACHE_VAL_SILENT([gl_cv_func___va_copy], [
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <stdarg.h>]],
|
||||
[[
|
||||
#ifndef __va_copy
|
||||
error, bail out
|
||||
#endif
|
||||
]])],
|
||||
[gl_cv_func___va_copy=yes],
|
||||
[gl_cv_func___va_copy=no])])
|
||||
if test $gl_cv_func___va_copy = yes; then
|
||||
AC_DEFINE([va_copy], [__va_copy],
|
||||
[Define as a macro for copying va_list variables.])
|
||||
else
|
||||
AH_VERBATIM([gl_VA_COPY], [/* A replacement for va_copy, if needed. */
|
||||
#define gl_va_copy(a,b) ((a) = (b))])
|
||||
AC_DEFINE([va_copy], [gl_va_copy],
|
||||
[Define as a macro for copying va_list variables.])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([STDARG_H])
|
||||
AM_CONDITIONAL([GL_GENERATE_STDARG_H], [test -n "$STDARG_H"])
|
||||
AC_SUBST([NEXT_STDARG_H])
|
||||
])
|
|
@ -1,5 +1,8 @@
|
|||
2011-05-04 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Use C99's va_copy to avoid undefined behavior on x86-64 GNU/Linux.
|
||||
* eval.c (verror): doprnt a copy of ap, not the original. (Bug#8545)
|
||||
|
||||
* eval.c (verror): OK to create a string of up to MOST_POSITIVE_FIXNUM
|
||||
bytes.
|
||||
|
||||
|
|
|
@ -2002,7 +2002,10 @@ verror (const char *m, va_list ap)
|
|||
|
||||
while (1)
|
||||
{
|
||||
used = doprnt (buffer, size, m, m + mlen, ap);
|
||||
va_list ap_copy;
|
||||
va_copy (ap_copy, ap);
|
||||
used = doprnt (buffer, size, m, m + mlen, ap_copy);
|
||||
va_end (ap_copy);
|
||||
|
||||
/* Note: the -1 below is because `doprnt' returns the number of bytes
|
||||
excluding the terminating null byte, and it always terminates with a
|
||||
|
|
Loading…
Add table
Reference in a new issue