| Summary: | SDL_SetError() and %lu | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Ozkan Sezer <sezeroz> |
| Component: | *don't know* | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | juha.niemimaki |
| Version: | HG 2.0 | ||
| Hardware: | All | ||
| OS: | All | ||
| Attachments: | SDL_SetError %l patch | ||
This bug is annoying, and it shows itself in windows (and os/2) builds
when LIBC is enabled, and it is in both SDL1.2 and SDL2. Consider the
following simple test case:
#include <stdio.h>
#include "SDL.h"
long l1 = 25;
long l2 = -7;
unsigned long u = 1024;
int main (void) {
SDL_Init(0); /* bah.. */
SDL_SetError("L = %ld",l1);
printf("%s\n",SDL_GetError());
SDL_SetError("L = %li",l2);
printf("%s\n",SDL_GetError());
SDL_SetError("L = %lu",u);
printf("%s\n",SDL_GetError());
SDL_Quit(); /* blah.. */
return 0;
}
It builds+links against both SDL1.2 and SDL2. Build, e.g. for windows.
Run with SDL.dll from SDL-1.2.15-win32-x64.zip, and it prints:
L = d
L = i
L = u
Run with an SDL2.dll from libsdl site, e.g.: SDL2-2.0.5-win32-x64.zip,
and it will print correctly: the difference is, I think, the SDL2.dll
is built with --disable-libc. (SDL_error.c clearly does not handle %l,
so how does it print correctly??)
Build on linux and run, it will print print correctly again. (magic?)
If I apply the following patch to support %ld, %li and %lu, it prints
correctly: only briefly tested, very possibly inefficient and clearly
needs review.
diff --git a/src/SDL_error.c b/src/SDL_error.c
--- a/src/SDL_error.c
+++ b/src/SDL_error.c
@@ -76,6 +76,16 @@
case 0: /* Malformed format string.. */
--fmt;
break;
+ case 'l':
+ switch (*fmt++) {
+ case 0: /* Malformed format string.. */
+ --fmt;
+ break;
+ case 'i': case 'd': case 'u':
+ error->args[error->argc++].value_li = va_arg(ap, long);
+ break;
+ }
+ break;
case 'c':
case 'i':
case 'd':
@@ -219,6 +229,22 @@
&& spot < (tmp + SDL_arraysize(tmp) - 2)) {
*spot++ = *fmt++;
}
+ if (*fmt == 'l') {
+ *spot++ = *fmt++;
+ *spot++ = *fmt++;
+ *spot++ = '\0';
+ switch (spot[-2]) {
+ case 'i': case 'd': case 'u':
+ len = SDL_snprintf(msg, maxlen, tmp,
+ error->args[argi++].value_li);
+ if (len > 0) {
+ msg += len;
+ maxlen -= len;
+ }
+ break;
+ }
+ continue;
+ }
*spot++ = *fmt++;
*spot++ = '\0';
switch (spot[-2]) {
diff --git a/src/SDL_error_c.h b/src/SDL_error_c.h
--- a/src/SDL_error_c.h
+++ b/src/SDL_error_c.h
@@ -51,6 +51,7 @@
unsigned char value_c;
#endif
int value_i;
+ long value_li;
double value_f;
char buf[ERR_MAX_STRLEN];
} args[ERR_MAX_ARGS];
This bug makes testerror crash on AmigaOS 4 (32-bit PowerPC). Does the patch above from comment #1 make it work for you? Created attachment 3048 [details]
SDL_SetError %l patch
Adding my proposed patch as an attachment.
(In reply to Ozkan Sezer from comment #3) > Does the patch above from comment #1 make it work for you? Yes, it seems to cure the crash. Has anyone had a chance to review the patch from comment #4 ? Pushed, thanks! https://hg.libsdl.org/SDL/rev/91138f56d762 |
As far as I can see SDL_SetError() doesn't handle %lu, but testerror.c feeds %lu to it. (Or, am I missing something?) Lazy solution would be changing ThreadFunc() in test/testerror.c, like: diff -r f7abcb63e51e test/testerror.c --- a/test/testerror.c Sun Aug 13 01:00:01 2017 -0400 +++ b/test/testerror.c Sun Aug 13 11:21:40 2017 +0300 @@ -31,8 +31,8 @@ int SDLCALL ThreadFunc(void *data) { /* Set the child thread error string */ - SDL_SetError("Thread %s (%lu) had a problem: %s", - (char *) data, SDL_ThreadID(), "nevermind"); + SDL_SetError("Thread %s (%u) had a problem: %s", + (char *) data, (unsigned int) SDL_ThreadID(), "nevermind"); while (alive) { SDL_Log("Thread '%s' is alive!\n", (char *) data); SDL_Delay(1 * 1000);