We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 3739

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

Description Ozkan Sezer 2017-08-13 10:43:40 UTC
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);
Comment 1 Ozkan Sezer 2017-08-21 15:16:34 UTC
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];
Comment 2 Juha Niemimäki 2017-10-28 13:16:52 UTC
This bug makes testerror crash on AmigaOS 4 (32-bit PowerPC).
Comment 3 Ozkan Sezer 2017-10-29 10:50:08 UTC
Does the patch above from comment #1 make it work for you?
Comment 4 Ozkan Sezer 2017-10-29 11:20:41 UTC
Created attachment 3048 [details]
SDL_SetError %l patch

Adding my proposed patch as an attachment.
Comment 5 Juha Niemimäki 2017-10-29 12:24:10 UTC
(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.
Comment 6 Ozkan Sezer 2018-02-15 08:20:54 UTC
Has anyone had a chance to review the patch from comment #4 ?
Comment 7 Sam Lantinga 2018-02-15 19:16:58 UTC
Pushed, thanks!
https://hg.libsdl.org/SDL/rev/91138f56d762