From cdb82f6fbbdf0c747b8eb83bd3516bef0707fc62 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 20 Mar 2019 15:29:04 +0100 Subject: [PATCH] LibC: Fix bug in scanf() family where we'd capture invalid data. --- LibC/scanf.cpp | 66 ++++++++++++-------------------------------------- LibC/stdio.cpp | 36 +++++++++++++++++++++++++++ LibC/stdio.h | 2 ++ 3 files changed, 54 insertions(+), 50 deletions(-) diff --git a/LibC/scanf.cpp b/LibC/scanf.cpp index 27b0699a80..4aaa818177 100644 --- a/LibC/scanf.cpp +++ b/LibC/scanf.cpp @@ -33,8 +33,6 @@ #include #include -#define MAXLN 512 - static const char* determine_base(const char* p, int& base) { if (p[0] == '0') { @@ -119,54 +117,13 @@ int atob(unsigned int* vp, const char* p, int base) return 0; } -static int vfscanf(FILE*, const char*, va_list); -static int vsscanf(const char*, const char*, va_list); - #define ISSPACE " \t\n\r\f\v" -int scanf(const char* fmt, ...) -{ - int count; - va_list ap; - - va_start(ap, fmt); - count = vfscanf(stdin, fmt, ap); - va_end(ap); - return count; -} - -int fscanf(FILE *fp, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - int count = vfscanf(fp, fmt, ap); - va_end(ap); - return count; -} - -int sscanf(const char *buf, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - int count = vsscanf(buf, fmt, ap); - va_end(ap); - return count; -} - -static int vfscanf(FILE *fp, const char* fmt, va_list ap) -{ - char buf[MAXLN + 1]; - if (!fgets(buf, MAXLN, fp)) - return -1; - int count = vsscanf(buf, fmt, ap); - return count; -} - -static int vsscanf(const char *buf, const char *s, va_list ap) +int vsscanf(const char *buf, const char *s, va_list ap) { int base = 10; char *t; - char tmp[MAXLN]; + char tmp[BUFSIZ]; bool noassign = false; int count = 0; int width = 0; @@ -220,16 +177,25 @@ static int vsscanf(const char *buf, const char *s, va_list ap) else if (*s == 'b') base = 2; if (!width) { - if (isspace(*(s + 1)) || *(s + 1) == 0) + if (isspace(*(s + 1)) || *(s + 1) == 0) { width = strcspn(buf, ISSPACE); - else - width = strchr(buf, *(s + 1)) - buf; + } else { + auto* p = strchr(buf, *(s+1)); + if (p) + width = p - buf; + else { + noassign = true; + width = 0; + } + } } strncpy(tmp, buf, width); tmp[width] = '\0'; buf += width; - if (!noassign) - atob(va_arg(ap, uint32_t*), tmp, base); + if (!noassign) { + if (!atob(va_arg(ap, uint32_t*), tmp, base)) + noassign = true; + } } if (!noassign) ++count; diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index 2b8e9186bf..5576795f6c 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -424,5 +424,41 @@ int remove(const char* pathname) return rmdir(pathname); } +int scanf(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int count = vfscanf(stdin, fmt, ap); + va_end(ap); + return count; +} + +int fscanf(FILE* stream, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int count = vfscanf(stream, fmt, ap); + va_end(ap); + return count; +} + +int sscanf(const char* buffer, const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int count = vsscanf(buffer, fmt, ap); + va_end(ap); + return count; +} + +int vfscanf(FILE* stream, const char* fmt, va_list ap) +{ + char buffer[BUFSIZ]; + if (!fgets(buffer, sizeof(buffer) - 1, stream)) + return -1; + return vsscanf(buffer, fmt, ap); +} + + } diff --git a/LibC/stdio.h b/LibC/stdio.h index d07570c4a2..5a886cbff4 100644 --- a/LibC/stdio.h +++ b/LibC/stdio.h @@ -78,6 +78,8 @@ void perror(const char*); int scanf(const char* fmt, ...); int sscanf (const char* str, const char* fmt, ...); int fscanf(FILE*, const char* fmt, ...); +int vfscanf(FILE*, const char*, va_list); +int vsscanf(const char*, const char*, va_list); int setvbuf(FILE*, char* buf, int mode, size_t); void setbuf(FILE*, char* buf); void setlinebuf(FILE*);