LibC: Fix *scanf consuming extra characters

This commit is contained in:
Bananymous 2024-10-19 12:43:23 +03:00
parent 5fde2cf91a
commit 2464fccadd
3 changed files with 31 additions and 14 deletions

View File

@ -2,4 +2,4 @@
#include <stdarg.h> #include <stdarg.h>
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);

View File

@ -112,9 +112,9 @@ using BASE_TYPE = BAN::integral_constant<int, BASE>;
template<bool UNSIGNED> template<bool UNSIGNED>
using IS_UNSIGNED = BAN::integral_constant<bool, UNSIGNED>; using IS_UNSIGNED = BAN::integral_constant<bool, UNSIGNED>;
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; static constexpr int NONE = -2;
int nread = 0; int nread = 0;
@ -134,11 +134,9 @@ int scanf_impl(const char* format, va_list arguments, int (*__getc_fun)(void*),
{ {
if (in == DONE) if (in == DONE)
return; return;
if (advance || in == NONE) in = __getc_fun(advance, data);
{ if (advance)
in = __getc_fun(data);
nread++; nread++;
}
}; };
auto parse_integer_internal = auto parse_integer_internal =

View File

@ -794,11 +794,10 @@ char* tmpnam(char* storage)
return storage; return storage;
} }
int ungetc(int c, FILE* stream) int ungetc_unlocked(int c, FILE* stream)
{ {
if (c == EOF) if (c == EOF)
return EOF; return EOF;
ScopeLock _(stream);
if (stream->unget_char != EOF) if (stream->unget_char != EOF)
return EOF; return EOF;
stream->unget_char = c; stream->unget_char = c;
@ -806,6 +805,12 @@ int ungetc(int c, FILE* stream)
return (unsigned char)c; 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) int vfprintf(FILE* file, const char* format, va_list arguments)
{ {
ScopeLock _(file); 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) int vfscanf(FILE* file, const char* format, va_list arguments)
{ {
ScopeLock _(file); ScopeLock _(file);
return scanf_impl(format, arguments, [](void* file) { return getc_unlocked(static_cast<FILE*>(file)); }, file); return scanf_impl(format, arguments,
[](bool advance, void* data)
{
FILE* fp = static_cast<FILE*>(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) 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) int vsscanf(const char* s, const char* format, va_list arguments)
{ {
return scanf_impl(format, arguments, return scanf_impl(format, arguments,
[](void* data) -> int [](bool advance, void* data) -> int
{ {
char ret = **static_cast<char**>(data); const char** ptr = static_cast<const char**>(data);
(*static_cast<char**>(data))++;
if (advance)
(*ptr)++;
const char ret = **ptr;
if (ret == '\0') if (ret == '\0')
return -1; return EOF;
return ret; return ret;
}, &s }, &s
); );