diff options
author | Will Newton <will.newton@imgtec.com> | 2012-10-16 11:54:39 +0100 |
---|---|---|
committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2012-10-31 15:22:15 +0100 |
commit | 3d45b959518c375d07766f1826783a7072e2d450 (patch) | |
tree | 751197205d228bff5433faf5234193df453a2b41 | |
parent | 1ca62f5d3c57825924e62f41614eda00d888bd62 (diff) |
_scanf.c: Implement 'm' modifier for 'c' and '[' conversions.
The current code implements the 'm' modifier only for 's'
conversions and would cause a segfault if it was used for 'c'
or '[' conversions. This patch extends the code to cover these
cases too.
Signed-off-by: Will Newton <will.newton@imgtec.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
-rw-r--r-- | libc/stdio/_scanf.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/libc/stdio/_scanf.c b/libc/stdio/_scanf.c index 9aa1d52e8..ce9fc71bc 100644 --- a/libc/stdio/_scanf.c +++ b/libc/stdio/_scanf.c @@ -1352,7 +1352,21 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) (psfs.conv_num >= CONV_c) #endif /* __UCLIBC_HAS_WCHAR__ */ { + /* We might have to handle the allocation ourselves */ + int len; + unsigned char **ptr; + b = (psfs.store ? ((unsigned char *) psfs.cur_ptr) : buf); + /* With 'm', we actually got a pointer to a pointer */ + ptr = (void *)b; + + i = 0; + if (psfs.flags & FLAG_MALLOC) { + len = 0; + b = NULL; + } else + len = -1; + fail = 1; if (psfs.conv_num == CONV_c) { @@ -1360,31 +1374,25 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) sc.width = 1; } + if (psfs.flags & FLAG_MALLOC) + b = malloc(sc.width); + while (__scan_getc(&sc) >= 0) { zero_conversions = 0; - *b = sc.cc; - b += psfs.store; + b[i] = sc.cc; + i += psfs.store; } __scan_ungetc(&sc); if (sc.width > 0) { /* Failed to read all required. */ goto DONE; } + if (psfs.flags & FLAG_MALLOC) + *ptr = b; psfs.cnt += psfs.store; goto NEXT_FMT; } if (psfs.conv_num == CONV_s) { - /* We might have to handle the allocation ourselves */ - int len; - /* With 'm', we actually got a pointer to a pointer */ - unsigned char **ptr = (void *)b; - - i = 0; - if (psfs.flags & FLAG_MALLOC) { - len = 0; - b = NULL; - } else - len = -1; /* Yes, believe it or not, a %s conversion can store nuls. */ while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) { @@ -1400,10 +1408,6 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) fail = 0; } - if (psfs.flags & FLAG_MALLOC) - *ptr = b; - /* The code below takes care of terminating NUL */ - b += i; } else { #ifdef __UCLIBC_HAS_WCHAR__ assert((psfs.conv_num == CONV_LEFTBRACKET) || \ @@ -1459,8 +1463,14 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) if (!scanset[sc.cc]) { break; } - *b = sc.cc; - b += psfs.store; + if (i == len) { + /* Pick a size that won't trigger a lot of + * mallocs early on ... */ + len += 256; + b = realloc(b, len + 1); + } + b[i] = sc.cc; + i += psfs.store; fail = 0; } } @@ -1470,6 +1480,9 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) if (fail) { /* nothing stored! */ goto DONE; } + if (psfs.flags & FLAG_MALLOC) + *ptr = b; + b += i; *b = 0; /* Nul-terminate string. */ psfs.cnt += psfs.store; goto NEXT_FMT; |