Skip to content

Fix GH-21742: SplFileObject::fgets() throws at EOF in eof/fgets loop#46

Closed
iliaal wants to merge 1 commit intomasterfrom
fix/gh21742-fgets-eof
Closed

Fix GH-21742: SplFileObject::fgets() throws at EOF in eof/fgets loop#46
iliaal wants to merge 1 commit intomasterfrom
fix/gh21742-fgets-eof

Conversation

@iliaal
Copy link
Copy Markdown
Owner

@iliaal iliaal commented Apr 23, 2026

Fix in 08dad097025 made spl_filesystem_file_read_ex throw Cannot read from file on NULL-buffer. SplFileObject::fgets() now throws inside the documented while (!$spl->eof()) $spl->fgets(), because eof() returns false until a read attempt returns zero bytes, so the loop always makes one extra fgets call past the final newline.

Narrow fgets to silent=true and return empty string when the stream is at EOF; keep the throw for non-EOF read failures so userland wrappers that return NULL without setting EOF still surface the error. next, seek, current, fscanf keep the stricter semantics.

Fixes php#21742

The SplFileObject iterator-desync fix in 08dad09 made
spl_filesystem_file_read_ex throw "Cannot read from file" on the
NULL-buffer path. SplFileObject::fgets() now throws inside the
documented while (!$spl->eof()) $spl->fgets() idiom, because eof()
returns false until a read attempt returns zero bytes.

Keep the stricter semantics for next(), seek(), current(), fscanf().
Narrow fgets() to silent=true and return empty string on FAILURE,
restoring the PHP-8.5 contract.

Fixes phpGH-21742
@iliaal iliaal force-pushed the fix/gh21742-fgets-eof branch from 999edab to 8d8acc7 Compare April 23, 2026 14:54
@iliaal
Copy link
Copy Markdown
Owner Author

iliaal commented Apr 23, 2026

Superseded by php#21853.

@iliaal iliaal closed this Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feedback: Please let us know if #21679 fixes in SplFileObject will be backported or not

1 participant