diff options
Diffstat (limited to 'libc')
| -rw-r--r-- | libc/stdio/_scanf.c | 51 | 
1 files changed, 33 insertions, 18 deletions
| diff --git a/libc/stdio/_scanf.c b/libc/stdio/_scanf.c index d48fd1267..f2a96700b 100644 --- a/libc/stdio/_scanf.c +++ b/libc/stdio/_scanf.c @@ -1351,7 +1351,20 @@ 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; + +				if (psfs.flags & FLAG_MALLOC) { +					len = 0; +					b = NULL; +				} else +					len = -1; +  				fail = 1;  				if (psfs.conv_num == CONV_c) { @@ -1359,32 +1372,28 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg)  						sc.width = 1;  					} +					if (psfs.flags & FLAG_MALLOC) +						b = malloc(sc.width); + +					i = 0;  					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)) {  						zero_conversions = 0; @@ -1399,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) || \ @@ -1453,13 +1458,20 @@ int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg)  #endif /* __UCLIBC_HAS_WCHAR__ */ +					i = 0;  					while (__scan_getc(&sc) >= 0) {  						zero_conversions = 0;  						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;  					}  				} @@ -1469,6 +1481,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; | 
