Skip to content

Commit

Permalink
LibC: Make scanf always copy its va_list
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
dascandy authored and gunnarbeutner committed Jul 16, 2021
1 parent 3cca9e6 commit 85c2ad9
Showing 1 changed file with 5 additions and 1 deletion.
6 changes: 5 additions & 1 deletion Userland/Libraries/LibC/scanf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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('%')) {
Expand Down Expand Up @@ -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*)&copy : nullptr;

// Now try to read.
switch (conversion_specifier) {
Expand Down Expand Up @@ -616,6 +619,7 @@ extern "C" int vsscanf(const char* input, const char* format, va_list ap)
}
}
}
va_end(copy);

return elements_matched;
}

0 comments on commit 85c2ad9

Please sign in to comment.