From 441d9ba2b03fa4a990dbd7de1601ac92dd557fa4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 11 Aug 2017 19:36:12 -0700 Subject: [PATCH] Fixed bug 3341 - SDL_sscanf() problem e_pluschauskas Why does SDL_sscanf() always returns the number of format specifiers and doesn't implements standard C library behavior? --- src/stdlib/SDL_string.c | 42 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index fde92fc8ebb14..4368994edef36 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -78,7 +78,7 @@ SDL_ScanLong(const char *text, int radix, long *valuep) value += v; ++text; } - if (valuep) { + if (valuep && text > textstart) { if (negative && value) { *valuep = -value; } else { @@ -114,7 +114,7 @@ SDL_ScanUnsignedLong(const char *text, int radix, unsigned long *valuep) value += v; ++text; } - if (valuep) { + if (valuep && text > textstart) { *valuep = value; } return (text - textstart); @@ -146,7 +146,7 @@ SDL_ScanUintPtrT(const char *text, int radix, uintptr_t * valuep) value += v; ++text; } - if (valuep) { + if (valuep && text > textstart) { *valuep = value; } return (text - textstart); @@ -183,7 +183,7 @@ SDL_ScanLongLong(const char *text, int radix, Sint64 * valuep) value += v; ++text; } - if (valuep) { + if (valuep && text > textstart) { if (negative && value) { *valuep = -value; } else { @@ -219,7 +219,7 @@ SDL_ScanUnsignedLongLong(const char *text, int radix, Uint64 * valuep) value += v; ++text; } - if (valuep) { + if (valuep && text > textstart) { *valuep = value; } return (text - textstart); @@ -251,7 +251,7 @@ SDL_ScanFloat(const char *text, double *valuep) ++text; } } - if (valuep) { + if (valuep && text > textstart) { if (negative && value) { *valuep = -value; } else { @@ -1025,6 +1025,10 @@ SDL_vsscanf(const char *text, const char *fmt, va_list ap) { int retval = 0; + if (!text || !*text) { + return -1; + } + while (*fmt) { if (*fmt == ' ') { while (SDL_isspace((unsigned char) *text)) { @@ -1044,6 +1048,7 @@ SDL_vsscanf(const char *text, const char *fmt, va_list ap) DO_LONG, DO_LONGLONG } inttype = DO_INT; + size_t advance; SDL_bool suppress = SDL_FALSE; ++fmt; @@ -1131,8 +1136,9 @@ SDL_vsscanf(const char *text, const char *fmt, va_list ap) } } else { long value; - text += SDL_ScanLong(text, radix, &value); - if (!suppress) { + advance = SDL_ScanLong(text, radix, &value); + text += advance; + if (advance && !suppress) { switch (inttype) { case DO_SHORT: { @@ -1175,16 +1181,18 @@ SDL_vsscanf(const char *text, const char *fmt, va_list ap) case 'u': if (inttype == DO_LONGLONG) { Uint64 value; - text += SDL_ScanUnsignedLongLong(text, radix, &value); - if (!suppress) { + advance = SDL_ScanUnsignedLongLong(text, radix, &value); + text += advance; + if (advance && !suppress) { Uint64 *valuep = va_arg(ap, Uint64 *); *valuep = value; ++retval; } } else { unsigned long value; - text += SDL_ScanUnsignedLong(text, radix, &value); - if (!suppress) { + advance = SDL_ScanUnsignedLong(text, radix, &value); + text += advance; + if (advance && !suppress) { switch (inttype) { case DO_SHORT: { @@ -1216,8 +1224,9 @@ SDL_vsscanf(const char *text, const char *fmt, va_list ap) case 'p': { uintptr_t value; - text += SDL_ScanUintPtrT(text, 16, &value); - if (!suppress) { + advance = SDL_ScanUintPtrT(text, 16, &value); + text += advance; + if (advance && !suppress) { void **valuep = va_arg(ap, void **); *valuep = (void *) value; ++retval; @@ -1228,8 +1237,9 @@ SDL_vsscanf(const char *text, const char *fmt, va_list ap) case 'f': { double value; - text += SDL_ScanFloat(text, &value); - if (!suppress) { + advance = SDL_ScanFloat(text, &value); + text += advance; + if (advance && !suppress) { float *valuep = va_arg(ap, float *); *valuep = (float) value; ++retval;