diff --git a/libretro-common/include/streams/file_stream.h b/libretro-common/include/streams/file_stream.h index ab198b28eb..2bafc36b61 100644 --- a/libretro-common/include/streams/file_stream.h +++ b/libretro-common/include/streams/file_stream.h @@ -81,7 +81,7 @@ char* filestream_gets(RFILE *stream, char *s, size_t len); int filestream_getc(RFILE *stream); -int filestream_scanf(RFILE *stream, const char* format, ...); +int filestream_vscanf(RFILE *stream, const char* format, va_list *args); int filestream_eof(RFILE *stream); diff --git a/libretro-common/streams/file_stream.c b/libretro-common/streams/file_stream.c index c43423771c..b9def6f942 100644 --- a/libretro-common/streams/file_stream.c +++ b/libretro-common/streams/file_stream.c @@ -221,11 +221,11 @@ int filestream_getc(RFILE *stream) return EOF; } -int filestream_scanf(RFILE *stream, const char* format, ...) +int filestream_vscanf(RFILE *stream, const char* format, va_list *args) { char buf[4096]; char subfmt[64]; - va_list args; + va_list args_copy; const char * bufiter = buf; int ret = 0; int64_t startpos = filestream_tell(stream); @@ -236,7 +236,12 @@ int filestream_scanf(RFILE *stream, const char* format, ...) buf[maxlen] = '\0'; - va_start(args, format); + /* Have to copy the input va_list here + * > Calling va_arg() on 'args' directly would + * cause the va_list to have an indeterminate value + * in the function calling filestream_vscanf(), + * leading to unexpected behaviour */ + va_copy(args_copy, *args); while (*format) { @@ -302,7 +307,7 @@ int filestream_scanf(RFILE *stream, const char* format, ...) } else { - int v = sscanf(bufiter, subfmt, va_arg(args, void*), &sublen); + int v = sscanf(bufiter, subfmt, va_arg(args_copy, void*), &sublen); if (v == EOF) return EOF; if (v != 1) @@ -327,7 +332,7 @@ int filestream_scanf(RFILE *stream, const char* format, ...) } } - va_end(args); + va_end(args_copy); filestream_seek(stream, startpos+(bufiter-buf), RETRO_VFS_SEEK_POSITION_START); diff --git a/libretro-common/streams/file_stream_transforms.c b/libretro-common/streams/file_stream_transforms.c index 099b27b489..cc6965f7b1 100644 --- a/libretro-common/streams/file_stream_transforms.c +++ b/libretro-common/streams/file_stream_transforms.c @@ -153,7 +153,7 @@ int rfscanf(RFILE * stream, const char * format, ...) int result; va_list vl; va_start(vl, format); - result = filestream_scanf(stream, format, vl); + result = filestream_vscanf(stream, format, &vl); va_end(vl); return result; }