From 2464fccadd38e93313fdf44912b753560f38cf6a Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 19 Oct 2024 12:43:23 +0300 Subject: [PATCH] LibC: Fix *scanf consuming extra characters --- userspace/libraries/LibC/include/scanf_impl.h | 2 +- userspace/libraries/LibC/scanf_impl.cpp | 10 +++--- userspace/libraries/LibC/stdio.cpp | 33 +++++++++++++++---- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/userspace/libraries/LibC/include/scanf_impl.h b/userspace/libraries/LibC/include/scanf_impl.h index 87411dbd..0479e254 100644 --- a/userspace/libraries/LibC/include/scanf_impl.h +++ b/userspace/libraries/LibC/include/scanf_impl.h @@ -2,4 +2,4 @@ #include -int scanf_impl(const char* format, va_list arguments, int (*getc_fun)(void*), void* data); +int scanf_impl(const char* format, va_list arguments, int (*getc_fun)(bool advance, void*), void* data); diff --git a/userspace/libraries/LibC/scanf_impl.cpp b/userspace/libraries/LibC/scanf_impl.cpp index 0a3afb9e..b5b35c1f 100644 --- a/userspace/libraries/LibC/scanf_impl.cpp +++ b/userspace/libraries/LibC/scanf_impl.cpp @@ -112,9 +112,9 @@ using BASE_TYPE = BAN::integral_constant; template using IS_UNSIGNED = BAN::integral_constant; -int scanf_impl(const char* format, va_list arguments, int (*__getc_fun)(void*), void* data) +int scanf_impl(const char* format, va_list arguments, int (*__getc_fun)(bool advance, void*), void* data) { - static constexpr int DONE = -1; + static constexpr int DONE = EOF; static constexpr int NONE = -2; int nread = 0; @@ -134,11 +134,9 @@ int scanf_impl(const char* format, va_list arguments, int (*__getc_fun)(void*), { if (in == DONE) return; - if (advance || in == NONE) - { - in = __getc_fun(data); + in = __getc_fun(advance, data); + if (advance) nread++; - } }; auto parse_integer_internal = diff --git a/userspace/libraries/LibC/stdio.cpp b/userspace/libraries/LibC/stdio.cpp index bea1a6a3..90f05a56 100644 --- a/userspace/libraries/LibC/stdio.cpp +++ b/userspace/libraries/LibC/stdio.cpp @@ -794,11 +794,10 @@ char* tmpnam(char* storage) return storage; } -int ungetc(int c, FILE* stream) +int ungetc_unlocked(int c, FILE* stream) { if (c == EOF) return EOF; - ScopeLock _(stream); if (stream->unget_char != EOF) return EOF; stream->unget_char = c; @@ -806,6 +805,12 @@ int ungetc(int c, FILE* stream) return (unsigned char)c; } +int ungetc(int c, FILE* stream) +{ + ScopeLock _(stream); + return ungetc_unlocked(c, stream); +} + int vfprintf(FILE* file, const char* format, va_list arguments) { ScopeLock _(file); @@ -815,7 +820,18 @@ int vfprintf(FILE* file, const char* format, va_list arguments) int vfscanf(FILE* file, const char* format, va_list arguments) { ScopeLock _(file); - return scanf_impl(format, arguments, [](void* file) { return getc_unlocked(static_cast(file)); }, file); + return scanf_impl(format, arguments, + [](bool advance, void* data) + { + FILE* fp = static_cast(data); + + if (advance) + getc_unlocked(fp); + const int ret = getc_unlocked(fp); + ungetc_unlocked(ret, fp); + return ret; + }, file + ); } int vprintf(const char* format, va_list arguments) @@ -883,12 +899,15 @@ int vsprintf(char* buffer, const char* format, va_list arguments) int vsscanf(const char* s, const char* format, va_list arguments) { return scanf_impl(format, arguments, - [](void* data) -> int + [](bool advance, void* data) -> int { - char ret = **static_cast(data); - (*static_cast(data))++; + const char** ptr = static_cast(data); + + if (advance) + (*ptr)++; + const char ret = **ptr; if (ret == '\0') - return -1; + return EOF; return ret; }, &s );