In some cases, the php://input stream returns incorrect data.
This was discovered as a data corruption when directly parsing
a POSTed XML with a long text-node.

The problem is between main/streams/streams.c and
ext/standard/php_fopen_wrapper.c.

The XML parser requests data from the stream in 4000 byte
chunks.

_php_stream_read requests data from the handler for php://input
in 8192 byte chunks.  It uses two counters stream->readpos
and stream->writepos to handle the buffering.  Just before
returning the next 4000 byte chunk, _php_stream_read advances
the stream->position.

The handler for php://input in php_stream_input_read
uses stream->position to address the contents of
SG(request_info).raw_post_data and serves a 8192 byte chunk
starting at that position.

The problem shows itself on the third call of _php_stream_read.
In the first iteration of the while(size>0) loop, it uses the
192 bytes left over in the buffer.  In the second iteration it
needs to refill to buffer, so it calls php_stream_input_read.
But stream->position has not been advanced by 192 yet, so
php_stream_input_read ends up returning a buffer starting with
the same 192 bytes.

The patch consists in simply updating stream->position
immediately, instead of accumulating didread and only updating
stream->position at the end.  This way php_stream_input_read
always sees an accurate value of the stream->position.

Here it is.  It is made against php-5.0.3, but it also applies
to php5-200503161930.

==== begin ====
diff -ru php-5.0.3.orig/main/streams/streams.c php-5.0.3/main/streams/streams.c
--- php-5.0.3.orig/main/streams/streams.c       2004-11-15 15:44:14.000000000 
-0800
+++ php-5.0.3/main/streams/streams.c    2005-03-16 13:08:02.000000000 -0800
@@ -560,6 +560,7 @@
                        size -= toread;
                        buf += toread;
                        didread += toread;
+                       stream->position += toread;
                }
 
                /* ignore eof here; the underlying state might have changed */
@@ -584,6 +585,7 @@
                }
                if (toread > 0) {
                        didread += toread;
+                       stream->position += toread;
                        buf += toread;
                        size -= toread;
                } else {
@@ -596,10 +598,6 @@
                        break;
        }
 
-       if (didread > 0) {
-               stream->position += didread;
-       }
-
        return didread;
 }

==== end ====

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to