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