Commit Graph
11 Commits
Author SHA1 Message Date
Dean GalvinandAlex Whitehouse 7b1e946059 fix(libc): hold the stream lock across a resolved seek
fseeko now turns SEEK_CUR into ftello plus an absolute host seek, so two
threads making relative seeks on the same stream could both read the
same position and lose one of the moves. Hold the stream lock from the
target check to the end of the host seek, as the single host call did
before, and add a two-thread relative-seek test.

Co-authored-by: Alex Whitehouse <[email protected]>
2026-11-07 14:25:33 +13:00
Alex WhitehouseandClaude Opus 5.5 290990d400 fix(libc): keep buffered input when a seek target is rejected
Check fseeko targets on every host before the host C library sees
them, as FreeBSD 11.4's _fseeko does: a negative SEEK_SET, SEEK_CUR or
regular-file SEEK_END target fails with EINVAL and one past OFF_MAX
with EOVERFLOW, leaving the buffer, pushback and EOF state alone. This
replaces the Windows-only check for targets before the start of the
file: UCRT also dropped the read buffer for an overflowing SEEK_CUR
target, and glibc dropped pending ungetc data and returned EINVAL for
an overflowing target.

SEEK_END on a stream in write mode or on a nonregular file still goes
to the host library instead of being flushed to find its end.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 01:02:47 +00:00
Dean GalvinandOpensource55 dac6b65ab6 fix(libc): flush before reading the length for a SEEK_END bounds check on Windows
_filelengthi64 reads the size on disk and misses bytes still in the stdio write buffer, so a valid negative SEEK_END seek after an unflushed fwrite was rejected with EINVAL. Flush first, and cover it with a test that seeks from the end right after a buffered write.

Co-authored-by: Opensource55 <[email protected]>
2026-11-07 08:27:54 +13:00
Opensource55 d09671fecb fix(libc): keep the stream position when a seek before the start is rejected on Windows
The UCRT drops a stream's read buffer before its `lseek` to a negative target fails with
`EINVAL`, so a rejected `fseeko` or `fsetpos` left the stream at the descriptor's read-ahead
offset: after 4 of 8 buffered bytes, a rejected `fsetpos` to -1 reported the position as 8 and
the next read returned EOF. FreeBSD 11.4's `_fseeko` keeps the buffer and the position when
`_sseek` fails.

`fseeko` now rejects a target before the start of the file before the host stream is touched,
computing the base from `_ftelli64` for `SEEK_CUR` and `_filelengthi64` for `SEEK_END`, and
answers `EINVAL` with the stream unchanged. A target that is not negative still goes to
`_fseeki64`, and a host seek that fails for another reason behaves as before.

`file_position` gains the three rejected targets: `fsetpos` to -1 after 4 buffered bytes,
`fseeko` with `SEEK_CUR` past the start, and `fseeko` with `SEEK_END` past the start; each
asserts `EINVAL`, an unchanged `fgetpos` and the next byte read.
2026-11-06 01:10:18 +08:00
johnohhh1 3e848ba9ee fix(tests): open file position scratch stream under Unicode TEMP 2026-11-02 16:41:49 -05:00
Dean f4fa6e4ca5 Merge pull request #12480 from Oscar45397/test/libc-fgetpos-fsetpos
test(libc): check fsetpos clears end of file and rejects a negative position
2026-11-03 02:38:03 +13:00
Oscar45397andClaude Opus 5.5 31b8c2ba6a test(libc): cover fseek to a negative offset, from the end and past the end
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-31 02:07:28 +01:00
bunbeans2-archandClaude Opus 5.5 6878d1be40 fix(tests): open scratch streams under a Unicode TEMP on Windows
On Windows, std::tmpfile() returns NULL with errno 22 when %TEMP%
contains a character outside the ANSI code page, where GetTempPathA
returns '?' in its place. Fifteen tests that capture output through it
aborted. TemporaryFile::Open() opens a unique delete-on-close file under
temp_directory_path() with _wfopen; other hosts keep std::tmpfile().

Part of #13083

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 18:21:00 +01:00
Oscar45397andClaude Opus 5.5 e43e1385fe test(libc): check fsetpos clears end of file and rejects a negative position
FilePosition checked fgetpos and fsetpos only on a freshly written
stream. It now reads three bytes and requires fgetpos to give 3, reads
to end of file and requires fsetpos back to 3 to clear the end-of-file
indicator (C11 7.21.9.3) so the next fgetc returns the fourth byte, and
requires fsetpos to -1 to fail with EINVAL as FreeBSD's fseeko does.

A rejected seek on Windows still moves the stream, because the UCRT
drops its read buffer before the failing lseek: recorded in libc's
technical debt instead of asserted.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-28 22:04:45 +01:00
boykopovar f38d29fd08 refactor(sdk): add canonical headers for remaining libraries 2026-10-24 23:17:42 +03:00
RomainROCH 99fbcf0377 fix(libc): propagate file position errors 2026-10-02 06:15:14 +02:00