I finally got to the bottom of this bug. It was hiding nice and deep. I thought I'd run this by folks first before committing, as it impacts streams, which are pretty important :D . It passes the current tests, and I wrote test for it too. (below).
Index: main/streams/streams.c =================================================================== --- main/streams/streams.c (revision 287973) +++ main/streams/streams.c (working copy) @@ -901,10 +901,7 @@ } if (!e) { - if (seek_len < maxlen && !stream->eof) { - return NULL; - } - toread = maxlen; + toread = (seek_len < maxlen) ? seek_len : maxlen; } else { toread = e - (char *) stream->readbuf - stream->readpos; skip = 1; =======/ext/standard/tests/streams/bug49148.phpt:======= --TEST-- Bug #49148 (combination of stream_get_line and fseek does not work correctly) --FILE-- <?php // should give back "line 1" and "" $tmp = tmpfile(); fwrite($tmp, "line1\r\n"); fseek($tmp, 0); var_dump(stream_get_line($tmp, null, "\r\n")); var_dump(stream_get_line($tmp, null, "\r\n")); fclose($tmp); // should give back "line 1" and "" $tmp = tmpfile(); fwrite($tmp, "line1\r\n"); fseek($tmp, 0); var_dump(stream_get_line($tmp, null, "\r\n")); fseek($tmp, ftell($tmp)); // expected that this does not affect result. var_dump(stream_get_line($tmp, null, "\r\n")); fclose($tmp); // should give back "line 1" and "line 2" $tmp = tmpfile(); fwrite($tmp, "line1\r\n"); fwrite($tmp, "line2"); fseek($tmp, 0); var_dump(stream_get_line($tmp, null, "\r\n")); var_dump(stream_get_line($tmp, null, "\r\n")); fclose($tmp); // should give back "line 1" and "line 2" $tmp = tmpfile(); fwrite($tmp, "line1\r\n"); fwrite($tmp, "line2"); fseek($tmp, 0); var_dump(stream_get_line($tmp, null, "\r\n")); fseek($tmp, ftell($tmp)); // expected that this does not affect result. var_dump(stream_get_line($tmp, null, "\r\n")); fclose($tmp); // should give back "line 1" and "line 2" $tmp = tmpfile(); fwrite($tmp, "line1\r\n"); fwrite($tmp, "line2\r\n"); fseek($tmp, 0); var_dump(stream_get_line($tmp, null, "\r\n")); var_dump(stream_get_line($tmp, null, "\r\n")); fclose($tmp); // should give back "line 1" and "line 2" $tmp = tmpfile(); fwrite($tmp, "line1\r\n"); fwrite($tmp, "line2\r\n"); fseek($tmp, 0); var_dump(stream_get_line($tmp, null, "\r\n")); fseek($tmp, ftell($tmp)); // expected that this does not affect result. var_dump(stream_get_line($tmp, null, "\r\n")); fclose($tmp); ?> --EXPECT-- string(5) "line1" string(0) "" string(5) "line1" string(0) "" string(5) "line1" string(5) "line2" string(5) "line1" string(5) "line2" string(5) "line1" string(5) "line2" string(5) "line1" string(5) "line2" Garrett