mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 15:03:34 +00:00
f7ff515961
* 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. |
||
---|---|---|
.. | ||
BUILD.mk | ||
crypt_test.c | ||
devrand_test.c | ||
dirstream_test.c | ||
dtoa_test.c | ||
dumphexc_test.c | ||
ecvt_test.c | ||
fds_torture_test.c | ||
fgetln_test.c | ||
fgets_test.c | ||
fgetwc_test.c | ||
fmemopen_test.c | ||
fmt_test.c | ||
fprintf_test.c | ||
fputc_test.c | ||
fputs_test.c | ||
fread_test.c | ||
freopen_test.c | ||
fscanf_test.c | ||
fseeko_test.c | ||
ftell_test.c | ||
fwrite_test.c | ||
getdelim_test.c | ||
getentropy_test.c | ||
gz_test.c | ||
iconv_test.c | ||
joinstrlist_test.c | ||
memory_test.c | ||
mt19937_test.c | ||
palandprintf_test.c | ||
popen_test.c | ||
rand_test.c | ||
rngset_test.c | ||
snprintf_test.c | ||
sprintf_s.inc | ||
sprintf_s_test.c | ||
sscanf_test.c | ||
tmpfile_test.c | ||
ungetc_test.c | ||
vappendf_test.c | ||
zipdir_test.c |