Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:15467 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 77612 invoked by uid 1010); 16 Mar 2005 22:34:26 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 77597 invoked from network); 16 Mar 2005 22:34:26 -0000 Received: from unknown (HELO pb1.pair.com) (127.0.0.1) by localhost with SMTP; 16 Mar 2005 22:34:26 -0000 X-Host-Fingerprint: 208.25.178.70 u-tdftp.rd.francetelecom.com Received: from ([208.25.178.70:1607] helo=u-tdftp.rd.francetelecom.fr) by pb1.pair.com (ecelerity HEAD r(5124)) with SMTP id 38/98-08287-174B8324 for ; Wed, 16 Mar 2005 17:34:26 -0500 Received: from u-hatala.rd.francetelecom.com (U-HATALA.nmb [10.193.244.182]) by u-tdftp.rd.francetelecom.fr (Postfix) with ESMTP id 9A66E111DC0; Wed, 16 Mar 2005 14:34:22 -0800 (PST) Received: from u-hatala.rd.francetelecom.com (localhost [127.0.0.1]) by u-hatala.rd.francetelecom.com (8.13.3/8.13.3) with ESMTP id j2GMYMPO012013; Wed, 16 Mar 2005 14:34:22 -0800 Received: (from jozef@localhost) by u-hatala.rd.francetelecom.com (8.13.3/8.13.3/Submit) id j2GMYM0j012012; Wed, 16 Mar 2005 14:34:22 -0800 X-Authentication-Warning: u-hatala.rd.francetelecom.com: jozef set sender to phpint-bkrrym@skrt.org using -f Date: Wed, 16 Mar 2005 14:34:22 -0800 To: internals@lists.php.net Message-ID: <20050316223422.GB11662@u-hatala.rd.francetelecom.fr> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.7i Subject: [PATCH] Fix for php://input returning duplicate data in some cases From: phpint-bkrrym@skrt.org (Jozef Hatala) 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 ====