mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
Turns out that on PPC, va_list is an array (effectivly typedef struct
__va_list_tag va_list[1];) which causes grief when attempting to reuse va_list variables (eg, in vsnprintf retry loops). This is the reason for MisterP's crashes as the pointers in va_list no longer point to valid data. acinclude.m4: shamelessly steal the va_list, va_copy and __va_copy macros from cdda2wav but modified so AC_DEFINE includes the description (so acconfig.h can remain gone) configure.ac: use AC_TYPE_VA_LIST, AC_FUNC_VA_COPY and AC_FUNC_VA__COPY dstring.c: stash the incoming va_list args in a temp var before calling vsnprintf then restore them each time before retrying, but only if va_list is an array (hopefully this is ok for when va_list is a structure)
This commit is contained in:
parent
ed0342e996
commit
55a5c39187
3 changed files with 81 additions and 0 deletions
61
acinclude.m4
61
acinclude.m4
|
@ -340,3 +340,64 @@ AC_SUBST(XMMS_OUTPUT_PLUGIN_DIR)
|
|||
AC_SUBST(XMMS_GENERAL_PLUGIN_DIR)
|
||||
AC_SUBST(XMMS_EFFECT_PLUGIN_DIR)
|
||||
])
|
||||
|
||||
dnl Checks if function/macro va_copy() is available
|
||||
dnl Defines HAVE_VA_COPY on success.
|
||||
AC_DEFUN(AC_FUNC_VA_COPY,
|
||||
[AC_CACHE_CHECK([for va_copy], ac_cv_func_va_copy,
|
||||
[AC_TRY_LINK([
|
||||
#ifdef HAVE_STDARG_H
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif],
|
||||
[
|
||||
va_list a, b;
|
||||
|
||||
va_copy(a, b);],
|
||||
[ac_cv_func_va_copy=yes],
|
||||
[ac_cv_func_va_copy=no])])
|
||||
if test $ac_cv_func_va_copy = yes; then
|
||||
AC_DEFINE(HAVE_VA_COPY, 1, [Define if va_copy is available])
|
||||
fi])
|
||||
|
||||
dnl Checks if function/macro __va_copy() is available
|
||||
dnl Defines HAVE__VA_COPY on success.
|
||||
AC_DEFUN(AC_FUNC__VA_COPY,
|
||||
[AC_CACHE_CHECK([for __va_copy], ac_cv_func__va_copy,
|
||||
[AC_TRY_LINK([
|
||||
#ifdef HAVE_STDARG_H
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif],
|
||||
[
|
||||
va_list a, b;
|
||||
|
||||
__va_copy(a, b);],
|
||||
[ac_cv_func__va_copy=yes],
|
||||
[ac_cv_func__va_copy=no])])
|
||||
if test $ac_cv_func__va_copy = yes; then
|
||||
AC_DEFINE(HAVE__VA_COPY, 1, [Define if __va_copy is available])
|
||||
fi])
|
||||
|
||||
dnl Checks if va_list is an array
|
||||
dnl Defines VA_LIST_IS_ARRAY on success.
|
||||
AC_DEFUN(AC_TYPE_VA_LIST,
|
||||
[AC_CACHE_CHECK([if va_list is an array], ac_cv_type_va_list_array,
|
||||
[AC_TRY_LINK([
|
||||
#ifdef HAVE_STDARG_H
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
],
|
||||
[
|
||||
va_list a, b;
|
||||
|
||||
a = b;],
|
||||
[ac_cv_type_va_list_array=no],
|
||||
[ac_cv_type_va_list_array=yes])])
|
||||
if test $ac_cv_type_va_list_array = yes; then
|
||||
AC_DEFINE(VA_LIST_IS_ARRAY, 1, [Define if va_list is an array])
|
||||
fi])
|
||||
|
|
|
@ -172,6 +172,8 @@ AC_STRUCT_ST_BLKSIZE
|
|||
AC_HEADER_TIME
|
||||
AC_STRUCT_TM
|
||||
|
||||
AC_TYPE_VA_LIST
|
||||
|
||||
if test "x$cross_compiling" = xyes; then
|
||||
AC_MSG_CHECKING(whether byte ordering is bigendian)
|
||||
AC_ARG_WITH(endian,
|
||||
|
@ -321,6 +323,8 @@ AC_FUNC_MEMCMP
|
|||
AC_FUNC_MMAP
|
||||
AC_TYPE_SIGNAL
|
||||
AC_FUNC_VPRINTF
|
||||
AC_FUNC_VA_COPY
|
||||
AC_FUNC__VA_COPY
|
||||
AC_CHECK_FUNCS(
|
||||
access _access \
|
||||
gethostname gethostbyname connect gettimeofday getwd mkdir _mkdir \
|
||||
|
|
|
@ -164,11 +164,24 @@ dstring_clearstr (dstring_t *dstr)
|
|||
dstr->str[0] = 0;
|
||||
}
|
||||
|
||||
#if defined (HAVE_VA_COPY)
|
||||
# define VA_COPY(a,b) va_copy (a, b)
|
||||
#elif defined (HAVE__VA_COPY)
|
||||
# define VA_COPY(a,b) __va_copy (a, b)
|
||||
#else
|
||||
# define VA_COPY memcpy (a, b, sizeof (a))
|
||||
#endif
|
||||
|
||||
int
|
||||
dvsprintf (dstring_t *dstr, const char *fmt, va_list args)
|
||||
{
|
||||
int size;
|
||||
|
||||
#ifdef VA_LIST_IS_ARRAY
|
||||
va_list tmp_args;
|
||||
VA_COPY (tmp_args, args);
|
||||
#endif
|
||||
|
||||
size = vsnprintf (dstr->str, dstr->truesize, fmt, args) + 1; // +1 for nul
|
||||
while (size <= 0 || size > dstr->truesize) {
|
||||
if (size > 0)
|
||||
|
@ -176,6 +189,9 @@ dvsprintf (dstring_t *dstr, const char *fmt, va_list args)
|
|||
else
|
||||
dstr->size = dstr->truesize + 1024;
|
||||
dstring_adjust (dstr);
|
||||
#ifdef VA_LIST_IS_ARRAY
|
||||
VA_COPY (args, tmp_args);
|
||||
#endif
|
||||
size = vsnprintf (dstr->str, dstr->truesize, fmt, args) + 1;
|
||||
}
|
||||
dstr->size = size;
|
||||
|
|
Loading…
Reference in a new issue