Fix #252: gd_error() garbles variable arguments
Currently gd_error() forwards to gd_error_ex(). However, both functions accept a variable number of arguments, and simply forwarding the va_list isn't portable, see <http://c-faq.com/varargs/handoff.html>. This article also describes the usual workaround, namely to let the second function accept a va_list instead of variable number of arguments. We do so by introducing a static helper, what does not affect API/ABI compatibility.master
parent
bbb5939f65
commit
9fd6021e12
13
src/gd.c
13
src/gd.c
|
@ -96,12 +96,19 @@ void gd_stderr_error(int priority, const char *format, va_list args)
|
|||
|
||||
static gdErrorMethod gd_error_method = gd_stderr_error;
|
||||
|
||||
static void _gd_error_ex(int priority, const char *format, va_list args)
|
||||
{
|
||||
if (gd_error_method) {
|
||||
gd_error_method(priority, format, args);
|
||||
}
|
||||
}
|
||||
|
||||
void gd_error(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
gd_error_ex(GD_WARNING, format, args);
|
||||
_gd_error_ex(GD_WARNING, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
void gd_error_ex(int priority, const char *format, ...)
|
||||
|
@ -109,9 +116,7 @@ void gd_error_ex(int priority, const char *format, ...)
|
|||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
if (gd_error_method) {
|
||||
gd_error_method(priority, format, args);
|
||||
}
|
||||
_gd_error_ex(priority, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ if (BUILD_TEST)
|
|||
bmp
|
||||
freetype
|
||||
gd
|
||||
gd_error
|
||||
gd2
|
||||
gdimagearc
|
||||
gdimagecolorclosest
|
||||
|
|
|
@ -15,6 +15,7 @@ TESTS =
|
|||
include bmp/Makemodule.am
|
||||
include freetype/Makemodule.am
|
||||
include gd/Makemodule.am
|
||||
include gd_error/Makemodule.am
|
||||
include gd2/Makemodule.am
|
||||
include gdimagearc/Makemodule.am
|
||||
include gdimagecolorclosest/Makemodule.am
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/bug00252
|
|
@ -0,0 +1,5 @@
|
|||
LIST(APPEND TESTS_FILES
|
||||
bug00252
|
||||
)
|
||||
|
||||
ADD_GD_TESTS()
|
|
@ -0,0 +1,5 @@
|
|||
libgd_test_programs += \
|
||||
gd_error/bug00252
|
||||
|
||||
EXTRA_DIST += \
|
||||
gd_error/CMakeLists.txt
|
|
@ -0,0 +1,24 @@
|
|||
/* See <https://github.com/libgd/libgd/issues/252>. */
|
||||
|
||||
#include "gd.h"
|
||||
#include "gd_errors.h"
|
||||
#include "gdtest.h"
|
||||
|
||||
void my_error_handler(int priority, const char *format, va_list args)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* The following works according to
|
||||
<https://www.gnu.org/software/libc/manual/html_node/Receiving-Arguments.html>.
|
||||
It might not be portable, though. */
|
||||
n = va_arg(args, int);
|
||||
gdTestAssert(n == 42);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
gdSetErrorMethod(my_error_handler);
|
||||
gd_error_ex(GD_WARNING, "The answer is %i\n", 42);
|
||||
gd_error("The answer is %i\n", 42);
|
||||
return gdNumFailures();
|
||||
}
|
Loading…
Reference in New Issue