From 490cccba3cfd5ba54ecb64a10fb63c2f0e94a67d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 18 Aug 2006 22:54:57 +0000
Subject: [PATCH] Andrew Biggs pointed out a "Expect: 100-continue" flaw where
 libcurl didn't send the whole request at once, even though the Expect: header
 was disabled by the application. An effect of this change is also that small
 (< 1024 bytes) POSTs are now always sent without Expect: header since we deem
 it more costly to bother about that than the risk that we send the data in
 vain.

---
 CHANGES            | 10 +++++++++-
 RELEASE-NOTES      |  2 +-
 lib/http.c         | 34 +++++++++++++++++-----------------
 lib/http.h         |  6 +++++-
 tests/data/test508 |  1 -
 tests/data/test510 |  1 -
 tests/data/test513 |  1 -
 tests/data/test515 |  1 -
 8 files changed, 32 insertions(+), 24 deletions(-)

diff --git a/CHANGES b/CHANGES
index b2c393858..bacba4bd8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,14 @@
 
                                   Changelog
 
+Daniel (19 August 2006)
+- Andrew Biggs pointed out a "Expect: 100-continue" flaw where libcurl didn't
+  send the whole request at once, even though the Expect: header was disabled
+  by the application. An effect of this change is also that small (< 1024
+  bytes) POSTs are now always sent without Expect: header since we deem it
+  more costly to bother about that than the risk that we send the data in
+  vain.
+
 Daniel (9 August 2006)
 - Armel Asselin made the CURLOPT_PREQUOTE option work fine even when
   CURLOPT_NOBODY is set true. PREQUOTE is then run roughly at the same place
@@ -13,7 +21,7 @@ Daniel (9 August 2006)
   transfer.
 
 Daniel (8 August 2006)
-- - Fixed a flaw in the "Expect: 100-continue" treatment. If you did two POSTs
+- Fixed a flaw in the "Expect: 100-continue" treatment. If you did two POSTs
   on a persistent connection and allowed the first to use that header, you
   could not disable it for the second request.
 
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index cab94828a..1f90ffe89 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -29,6 +29,6 @@ New curl mirrors:
 This release would not have looked like this without help, code, reports and
 advice from friends like these:
 
- Domenico Andreoli, Armel Asselin, Gisle Vanem, Yang Tse
+ Domenico Andreoli, Armel Asselin, Gisle Vanem, Yang Tse, Andrew Biggs
 
         Thanks! (and sorry if I forgot to mention someone)
diff --git a/lib/http.c b/lib/http.c
index 310c0a617..4df91be0a 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -2249,16 +2249,24 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 
       if(data->set.postfields) {
 
-        if((data->state.authhost.done || data->state.authproxy.done )
-           && (postsize < MAX_INITIAL_POST_SIZE)) {
-          /* If we're not done with the authentication phase, we don't expect
-             to actually send off any data yet. Hence, we delay the sending of
-             the body until we receive that friendly 100-continue response */
+        /* for really small posts we don't use Expect: headers at all, and for
+           the somewhat bigger ones we allow the app to disable it */
+        if(postsize > TINY_INITIAL_POST_SIZE) {
+          result = expect100(data, req_buffer);
+          if(result)
+            return result;
+        }
+        else
+          data->state.expect100header = FALSE;
 
-          /* The post data is less than MAX_INITIAL_PORT_SIZE, then append it
-             to the header. This limit is no magic limit but only set to
-             prevent really huge POSTs to get the data duplicated with
-             malloc() and family. */
+        if(!data->state.expect100header &&
+           (postsize < MAX_INITIAL_POST_SIZE))  {
+          /* if we don't use expect:-100  AND
+             postsize is less than MAX_INITIAL_POST_SIZE
+
+             then append the post data to the HTTP request header. This limit
+             is no magic limit but only set to prevent really huge POSTs to
+             get the data duplicated with malloc() and family. */
 
           result = add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
           if(result)
@@ -2297,18 +2305,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
           /* set the upload size to the progress meter */
           Curl_pgrsSetUploadSize(data, http->postsize);
 
-          result = expect100(data, req_buffer);
-          if(result)
-            return result;
-
           add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
         }
       }
       else {
-        result = expect100(data, req_buffer);
-        if(result)
-          return result;
-
         add_buffer(req_buffer, "\r\n", 2); /* end of headers! */
 
         if(data->set.postfieldsize) {
diff --git a/lib/http.h b/lib/http.h
index e84e28b07..1c8ee7e39 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -74,7 +74,11 @@ int Curl_http_should_fail(struct connectdata *conn);
    It must not be greater than 64K to work on VMS.
 */
 #ifndef MAX_INITIAL_POST_SIZE
-#define MAX_INITIAL_POST_SIZE 1024
+#define MAX_INITIAL_POST_SIZE (64*1024)
+#endif
+
+#ifndef TINY_INITIAL_POST_SIZE
+#define TINY_INITIAL_POST_SIZE 1024
 #endif
 
 #endif
diff --git a/tests/data/test508 b/tests/data/test508
index 3d3c6c9e0..9ebbaa92a 100644
--- a/tests/data/test508
+++ b/tests/data/test508
@@ -39,7 +39,6 @@ Host: 127.0.0.1:%HTTPPORT
 Accept: */*
 Content-Length: 45
 Content-Type: application/x-www-form-urlencoded
-Expect: 100-continue
 
 this is what we post to the silly web server
 </protocol>
diff --git a/tests/data/test510 b/tests/data/test510
index 79c2d11a6..1c883f18d 100644
--- a/tests/data/test510
+++ b/tests/data/test510
@@ -39,7 +39,6 @@ Host: 127.0.0.1:%HTTPPORT
 Accept: */*
 Transfer-Encoding: chunked
 Content-Type: application/x-www-form-urlencoded
-Expect: 100-continue
 
 3
 one
diff --git a/tests/data/test513 b/tests/data/test513
index 920cbcc17..44063bc18 100644
--- a/tests/data/test513
+++ b/tests/data/test513
@@ -30,7 +30,6 @@ Host: 127.0.0.1:%HTTPPORT
 Accept: */*
 Content-Length: 1
 Content-Type: application/x-www-form-urlencoded
-Expect: 100-continue
 
 </protocol>
 # 42 - aborted by callback
diff --git a/tests/data/test515 b/tests/data/test515
index f6be8c42c..566da84f4 100644
--- a/tests/data/test515
+++ b/tests/data/test515
@@ -40,7 +40,6 @@ Host: 127.0.0.1:%HTTPPORT
 Accept: */*
 Content-Length: 0
 Content-Type: application/x-www-form-urlencoded
-Expect: 100-continue
 
 </protocol>
 </verify>