From 85c2ad94d513fece80a76f822aca31fe45e6c51d Mon Sep 17 00:00:00 2001 From: Peter Bindels Date: Fri, 16 Jul 2021 22:01:35 +0200 Subject: [PATCH] LibC: Make scanf always copy its va_list On x86_64 GCC implements va_list as an array. This makes the syntax for taking a pointer to it break & crash. The workaround / solution is to create a copy. Since va_list is a tiny struct referencing the actual varargs, this is little overhead (especially compared to va_args itself) --- Userland/Libraries/LibC/scanf.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibC/scanf.cpp b/Userland/Libraries/LibC/scanf.cpp index ccdd63870c..cf46014eca 100644 --- a/Userland/Libraries/LibC/scanf.cpp +++ b/Userland/Libraries/LibC/scanf.cpp @@ -383,6 +383,9 @@ extern "C" int vsscanf(const char* input, const char* format, va_list ap) int elements_matched = 0; + va_list copy; + __builtin_va_copy(copy, ap); + while (!format_lexer.is_eof()) { format_lexer.ignore_while(isspace); if (!format_lexer.next_is('%')) { @@ -537,7 +540,7 @@ extern "C" int vsscanf(const char* input, const char* format, va_list ap) } } - auto* ap_or_null = !suppress_assignment ? (va_list*)&ap : nullptr; + auto* ap_or_null = !suppress_assignment ? (va_list*)© : nullptr; // Now try to read. switch (conversion_specifier) { @@ -616,6 +619,7 @@ extern "C" int vsscanf(const char* input, const char* format, va_list ap) } } } + va_end(copy); return elements_matched; }