cosmopolitan/libc/stdio
Ivan Komarov f7ff515961
*scanf() fixes to make TeX work (#1109)
* Fix reading the same symbol twice when using `{f,}scanf()`

PR #924 appears to use `unget()` subtly incorrectly when parsing
floating point numbers. The rest of the code only uses `unget()`
immediately followed by `goto Done;` to return back the symbol that
can't possibly belong to the directive we're processing.

With floating-point, however, the ungot characters could very well
be valid for the *next* directive, so we will essentially read them
twice. It can't be seen in `sscanf()` tests because `unget()` is a
no-op there, but the test I added for `fscanf()` fails like this:

        ...
        EXPECT_EQ(0xDEAD, i1)
                need 57005 (or 0xdead) =
                 got 908973 (or 0x000ddead)
        ...
        EXPECT_EQ(0xBEEF, i2)
                need 48879 (or 0xbeef) =
                 got 769775 (or 0x000bbeef)

This means we read 0xDDEAD instead of 0xDEAD and 0xBBEEF instead of
0xBEEF. I checked that both musl and glibc read 0xDEAD/0xBEEF, as
expected.

Fix the failing test by removing the unneeded `unget()` calls.

* Don't read invalid floating-point numbers in `*scanf()`

Currently, we just ignore any errors from `strtod()`. They can
happen either because no valid float can be parsed at all, or
because the state machine recognizes only a prefix of a valid
floating-point number.

Fix this by making sure `strtod()` parses everything we recognized,
provided it's non-empty. This requires to pop the last character
off the FP buffer, which is supposed to be parsed by the next
`*scanf()` directive.

* Make `%c` parsing in `*scanf()` respect the C standard

Currently, `%c`-style directives always succeed even if there
are actually fewer characters in the input than requested.

Before the fix, the added test fails like this:

        ...
        EXPECT_EQ(2, sscanf("ab", "%c %c %c", &c2, &c3, &c4))
                need 2 (or 0x02 or '\2' or ENOENT) =
                 got 3 (or 0x03 or '\3' or ESRCH)
        ...
        EXPECT_EQ(0, sscanf("abcd", "%5c", s2))
                need 0 (or 0x0 or '\0') =
                 got 1 (or 0x01 or '\1' or EPERM)

musl and glibc pass this test.
2024-02-23 07:15:30 -08:00
..
__fpurge.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
__freadahead.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
__freadptr.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
__freadptrinc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
__fseterr.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
alloc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
alphasort.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
append.h Make cosmo.h work a little better 2024-02-21 16:40:09 -08:00
appendd.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
appendf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
appendr.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
appends.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
appendstrlist.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
appendw.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
appendz.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
asprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
atof.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
big5.inc Add more missing libc functionality 2022-08-06 10:50:51 -07:00
BUILD.mk more modeline errata (#1019) 2023-12-16 23:07:10 -05:00
clearerr.c more modeline errata (#1019) 2023-12-16 23:07:10 -05:00
clearerr_unlocked.c more modeline errata (#1019) 2023-12-16 23:07:10 -05:00
codepages.inc Add more missing libc functionality 2022-08-06 10:50:51 -07:00
confstr.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ctermid.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
demangle.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
dirstream.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
dprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
dprintf.h Add dontthrow attribute to most libc functions 2024-01-09 01:26:03 -08:00
dumphexc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ecvt.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
fbufsize.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fclose.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fdopen.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
feof.c more modeline errata (#1019) 2023-12-16 23:07:10 -05:00
feof_unlocked.c more modeline errata (#1019) 2023-12-16 23:07:10 -05:00
ferror.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ferror_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fflush.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fflush.internal.h Reduce header complexity 2023-11-28 14:39:42 -08:00
fflush_unlocked.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
fflushimpl.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgetc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgetc_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgetln.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgetpos.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgets.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgets_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgetwc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgetwc_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgetws.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fgetws_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fileno.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fileno_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
flbf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fleaks.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
flockfile.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
flushlbf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fmemopen.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fmt.c Make improvements 2024-02-12 10:23:00 -08:00
fopen.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fopenflags.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fpending.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fprintf_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fpurge.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fputc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fputc_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fputs.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fputs_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fputwc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fputwc_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fputws.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fputws_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fread.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fread_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
freadable.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
freading.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
freestrlist.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
freopen.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fscanf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fseek.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fseek_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fsetlocking.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fsetpos.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ftell.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ftrylockfile.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ftw.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
ftw.h Add dontthrow attribute to most libc functions 2024-01-09 01:26:03 -08:00
funlockfile.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fwritable.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fwrite.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fwrite_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
fwriting.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
g_rando.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
gb18030.inc Add more missing libc functionality 2022-08-06 10:50:51 -07:00
gcvt.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
get_current_dir_name.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
getchar.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
getchar_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
getcwd.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
getdelim.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
getdelim_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
getentropy.c Bring back gc() function 2024-01-08 10:26:28 -08:00
getline.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
gets.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
getwchar.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
getwchar_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
hex.internal.h Reduce header complexity 2023-11-28 14:39:42 -08:00
hkscs.inc Add more missing libc functionality 2022-08-06 10:50:51 -07:00
iconv.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
iconv.h Reduce header complexity 2023-11-28 14:39:42 -08:00
internal.h Reduce header complexity 2023-11-28 14:39:42 -08:00
jis0208.inc Add more missing libc functionality 2022-08-06 10:50:51 -07:00
joinstrlist.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
kappendf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ksc.inc Add more missing libc functionality 2022-08-06 10:50:51 -07:00
kvappendf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
lcg.internal.h Reduce header complexity 2023-11-28 14:39:42 -08:00
legacychars.inc Add more missing libc functionality 2022-08-06 10:50:51 -07:00
lemur64.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
mt19937.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
nftw.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
pclose.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
popen.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
printargs.c Make improvements 2024-02-12 10:23:00 -08:00
printf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
putchar.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
putchar_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
puts.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
puts_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
putwc_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
putwchar.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
putwchar_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
rand.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
rand.h Add dontthrow attribute to most libc functions 2024-01-09 01:26:03 -08:00
random.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
rdseed.c Make improvements 2024-02-12 10:23:00 -08:00
real1.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
real2.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
real3.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
revjis.inc Add more missing libc functionality 2022-08-06 10:50:51 -07:00
rewind.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
rngset.c Make improvements 2024-02-12 10:23:00 -08:00
scandir.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
scanf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
setbuf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
setbuffer.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
setlinebuf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
setvbuf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
snprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
sortstrlist.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
sprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
srand.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
sscanf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
stdbuf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
stderr.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
stdin.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
stdio.h Make improvements 2024-02-12 10:23:00 -08:00
stdio_ext.h Add dontthrow attribute to most libc functions 2024-01-09 01:26:03 -08:00
stdout.c Release Cosmopolitan v3.3 2024-02-20 13:27:59 -08:00
strfry.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
strlist.internal.h Reduce header complexity 2023-11-28 14:39:42 -08:00
strtold.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
swprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
syscall.c Introduce getcpu() system call from glibc 2024-02-21 18:17:20 -08:00
syscall.h Introduce getcpu() system call from glibc 2024-02-21 18:17:20 -08:00
sysparam.h Reduce header complexity 2023-11-28 14:39:42 -08:00
tmpfile.c Bring back gc() function 2024-01-08 10:26:28 -08:00
tmpnam.c Make improvements 2024-02-12 10:23:00 -08:00
tmpnam_r.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ungetc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ungetc_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ungetwc.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
ungetwc_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vappendf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vasprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vcscanf.c *scanf() fixes to make TeX work (#1109) 2024-02-23 07:15:30 -08:00
vdprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
versionsort.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vfprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vfprintf_unlocked.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vfscanf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vigna.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vscanf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vsnprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vsprintf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
vsscanf.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
wcstod.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
wcstof.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00
wcstold.c flip et / noet in modelines 2023-12-07 22:17:11 -05:00