]> granicus.if.org Git - php/commitdiff
Fix bug #63240 on stream_get_line()
authorGustavo Lopes <glopes@nebm.ist.utl.pt>
Fri, 12 Oct 2012 18:00:37 +0000 (20:00 +0200)
committerGustavo Lopes <glopes@nebm.ist.utl.pt>
Fri, 12 Oct 2012 18:23:43 +0000 (20:23 +0200)
stream_get_line() could contain the delimiter string if that string
had more than one character. The bug manifested itself when a read on
the stream ended with part of the delimiter string and the read after
would start with the rest of the delimiter string; provided that
the data of first read did not complete the max length result of the
call to stream_get_line() with the partial delimiter used in that max
length return. In that case, the delimiter will still appear in
the result, divided in two subsequent return values. That is not a bug.

See <http://www.mail-archive.com/internals@lists.php.net/msg61325.html>

ext/standard/tests/streams/bug63240.phpt [new file with mode: 0644]
main/streams/streams.c

diff --git a/ext/standard/tests/streams/bug63240.phpt b/ext/standard/tests/streams/bug63240.phpt
new file mode 100644 (file)
index 0000000..7612c43
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #63240: stream_get_line() return contains delimiter string
+--FILE--
+<?php
+$fd = fopen('php://temp', 'r+');
+$delimiter = 'MM';
+$str = str_repeat('.', 8191) . $delimiter . "rest";
+fwrite($fd, $str);
+rewind($fd);
+$line = stream_get_line($fd, 9000, $delimiter);
+var_dump(strlen($line));
+$line = stream_get_line($fd, 9000, $delimiter);
+var_dump($line);
+?>
+--EXPECT--
+int(8191)
+string(4) "rest"
index dfd60940fcaab096e1ca4dd3116b9050c3f2bb1c..eec9b703499d0340ea541e324d082fae5dc85a1b 100644 (file)
@@ -989,9 +989,17 @@ PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *re
                if (has_delim) {
                        /* search for delimiter, but skip buffered_len (the number of bytes
                         * buffered before this loop iteration), as they have already been
-                        * searched for the delimiter */
+                        * searched for the delimiter.
+                        * The left part of the delimiter may still remain in the buffer,
+                        * so subtract up to <delim_len - 1> from buffered_len, which is
+                        * the ammount of data we skip on this search  as an optimization
+                        */
                        found_delim = _php_stream_search_delim(
-                               stream, maxlen, buffered_len, delim, delim_len TSRMLS_CC);
+                               stream, maxlen,
+                               buffered_len >= (delim_len - 1)
+                                               ? buffered_len - (delim_len - 1)
+                                               : 0,
+                               delim, delim_len TSRMLS_CC);
                        if (found_delim) {
                                break;
                        }