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:
Bill Currie 2002-04-15 22:17:02 +00:00
parent ed0342e996
commit 55a5c39187
3 changed files with 81 additions and 0 deletions

View file

@ -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])

View file

@ -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 \

View file

@ -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;