php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #50078 [PATCH] file upload fails with thttpd
Submitted: 2009-11-04 15:27 UTC Modified: 2018-07-14 13:05 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:2 (100.0%)
From: nishantkumar05 at gmail dot com Assigned: cmb (profile)
Status: Closed Package: Other web server
PHP Version: 5.3.0 OS: ubuntu 8.10
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: nishantkumar05 at gmail dot com
New email:
PHP Version: OS:

 

 [2009-11-04 15:27 UTC] nishantkumar05 at gmail dot com
Description:
------------
I have thttpd 2.1b patched with php-5.3.0. Try to upload file using POST 
request to this web server. Small files ( max of 600 bytes or so ) can 
be transferred, but big files, for which POST request will span multiple 
packets fails.

Reproduce code:
---------------
.php web page that reproduces this bug is: (upload.php) 
<form enctype="multipart/form-data" action="uploader.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="2000000" />
Choose a file to upload: <input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>

Expected result:
----------------
It should be able to upload file of any size successfully.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-11-04 15:36 UTC] nishantkumar05 at gmail dot com
This is the patch available.
=============================================================
diff -Nur php-5.3.0/sapi/thttpd/thttpd.c php-
5.3.0_mod/sapi/thttpd/thttpd.c
--- php-5.3.0/sapi/thttpd/thttpd.c	2008-12-31 03:15:49.000000000 
-0800
+++ php-5.3.0_mod/sapi/thttpd/thttpd.c	2009-11-02 19:02:28.000000000 
-0800
@@ -64,6 +64,9 @@
 #define TG(v) (thttpd_globals.v)
 #endif
 
+
+int read_pending_content( void ); 
+
 static int sapi_thttpd_ub_write(const char *str, uint str_length 
TSRMLS_DC)
 {
 	int n;
@@ -247,16 +250,77 @@
 
 static int sapi_thttpd_read_post(char *buffer, uint count_bytes 
TSRMLS_DC)
 {
-	size_t read_bytes = 0;
+	size_t read_bytes = 0, send2php_bytes = 0 ;
+	size_t buff_bytes = TG(hc)->read_idx - TG(hc)->checked_idx ;
 
-	if (TG(unconsumed_length) > 0) {
-		read_bytes = MIN(TG(unconsumed_length), count_bytes);
-		memcpy(buffer, TG(hc)->read_buf + TG(hc)->checked_idx, 
read_bytes);
-		TG(unconsumed_length) -= read_bytes;
-		CONSUME_BYTES(read_bytes);
+
+	if ( buff_bytes > 0 ) {
+		/*we might already have some bytes in read_buf to be 
sent to php module*/
+		read_bytes = buff_bytes;
+	}else if ( TG(hc)->contentlength > 0 ){
+		read_bytes=read_pending_content();	
+	}
+
+	if ( read_bytes ) {
+			send2php_bytes = MIN ( read_bytes, 
count_bytes);
+			memcpy(buffer, TG(hc)->read_buf + TG(hc)-
>checked_idx, send2php_bytes);
+			TG(hc)->contentlength -= send2php_bytes;
+			/*bringing the read_idx back to checked_idx, 
so we have more room to read
+			  the pending bytes from connection*/
+			if ( send2php_bytes == read_bytes ) {
+				TG(hc)->read_idx = TG(hc)->checked_idx 
;
+			} else {
+				/*memmove is costly: but for small 
devices we cant increase the buffer
+  				  size substantially. presuming that 
memmove doesnt use extra buffer
+				  internally*/
+				memmove(TG(hc)->read_buf + TG(hc)-
>checked_idx, 
+							TG(hc)-
>read_buf + TG(hc)->checked_idx + send2php_bytes ,
+							read_bytes-
count_bytes);
+				TG(hc)->read_idx = TG(hc)->checked_idx 
+ ( read_bytes - count_bytes )  ;
+			}
+
+			TG(unconsumed_length) -= send2php_bytes;
 	}
-	
-	return read_bytes;
+
+	return send2php_bytes;
+}
+
+
+/*
+ * Read the max possible (limited by the available buffer ) pending 
data
+ * from the network. hc->contenlength has been used to tell about the 
+ * pending data to be read from the network, hence onus is on the 
caller
+ * to modify it accordingly.
+ * It starts reading from checked_idx and updates the read_idx after 
reading.
+ * -nishant
+ * */
+int read_pending_content( void ) 
+{
+	int avail_buf= TG(hc)->read_size - TG(hc)->read_idx; 
+	int act_to_read=0,total_read=0,ctr=0;
+
+
+	if ( TG(hc)->contentlength < avail_buf ){
+		act_to_read = TG(hc)->contentlength;
+	} else {
+		act_to_read = avail_buf - 2;
+	}
+
+	while(total_read != act_to_read)
+	{
+		ctr = read(TG(hc)->conn_fd, &(TG(hc)->read_buf[TG(hc)-
>checked_idx]), act_to_read );
+		if(ctr < 0){
+			if( ( errno == EINTR ) || ( errno == EAGAIN ) 
){
+				continue;
+			}else{
+				break;
+			}
+		}
+		total_read += ctr;
+	}
+
+	TG(hc)->read_idx += total_read;
+	return total_read;
 }
 
 static char *sapi_thttpd_read_cookies(TSRMLS_D)
@@ -663,12 +727,14 @@
 		hc->do_keep_alive = 0;
 	}
 	
+#if 0
+	/*Its ok to have unconsumed bytes. We will consum in read_post 
function*/
 	if (hc->contentlength != -1
 			&& SIZEOF_UNCONSUMED_BYTES() < hc-
>contentlength) {
 		hc->read_body_into_mem = 1;
 		return 0;
 	}
-	
+#endif
 	thttpd_request_ctor(TSRMLS_C);
 
 	thttpd_module_main(show_source TSRMLS_CC);
=============================================================

thanks
Nishant
 [2009-11-20 10:22 UTC] asure007 at hotmail dot com
I've grabbed that patch and edited it back into something i could use, but it won't work for me. Can you upload it somewhere to wget ?

The error i get:
patch: **** malformed patch at line 100:  static char *sapi_thttpd_read_cookies(TSRMLS_D)
 [2018-07-14 13:05 UTC] cmb@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: cmb
 [2018-07-14 13:05 UTC] cmb@php.net
The thttp SAPI is no longer available as of PHP 7.0.0, so this
ticket is obsolete.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Oct 15 18:01:27 2024 UTC