Bug 1154268 - Fetch Request should not allow creating a GET request with a body by copying a PUT request. r=bkelly
authorNikhil Marathe <nsm.nikhil@gmail.com>
Wed, 13 May 2015 15:15:23 -0700
changeset 243770 6cb759cdb9ae00ad64f327baa5c20b0fddbaf5e3
parent 243769 9ada89ffc2dec400954374596564630d78b9c196
child 243771 eee8a7f02b1a5ce65ef3ac1c16338d4e3ade96b1
push id28753
push userkwierso@gmail.com
push dateThu, 14 May 2015 22:33:43 +0000
treeherdermozilla-central@07e2e15703cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1154268
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1154268 - Fetch Request should not allow creating a GET request with a body by copying a PUT request. r=bkelly
dom/fetch/Request.cpp
dom/tests/mochitest/fetch/test_request.js
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -122,24 +122,26 @@ GetRequestURLFromWorker(const GlobalObje
 } // anonymous namespace
 
 /*static*/ already_AddRefed<Request>
 Request::Constructor(const GlobalObject& aGlobal,
                      const RequestOrUSVString& aInput,
                      const RequestInit& aInit, ErrorResult& aRv)
 {
   nsRefPtr<InternalRequest> request;
+  bool inputRequestHasBody = false;
 
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
 
   if (aInput.IsRequest()) {
     nsRefPtr<Request> inputReq = &aInput.GetAsRequest();
     nsCOMPtr<nsIInputStream> body;
     inputReq->GetBody(getter_AddRefs(body));
     if (body) {
+      inputRequestHasBody = true;
       if (inputReq->BodyUsed()) {
         aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR);
         return nullptr;
       } else {
         inputReq->SetBodyUsed();
       }
     }
 
@@ -283,26 +285,28 @@ Request::Constructor(const GlobalObject&
     }
   }
 
   requestHeaders->Fill(*headers, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  if (aInit.mBody.WasPassed()) {
+  if (aInit.mBody.WasPassed() || inputRequestHasBody) {
     // HEAD and GET are not allowed to have a body.
     nsAutoCString method;
     request->GetMethod(method);
     // method is guaranteed to be uppercase due to step 14.2 above.
     if (method.EqualsLiteral("HEAD") || method.EqualsLiteral("GET")) {
       aRv.ThrowTypeError(MSG_NO_BODY_ALLOWED_FOR_GET_AND_HEAD);
       return nullptr;
     }
+  }
 
+  if (aInit.mBody.WasPassed()) {
     const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& bodyInit = aInit.mBody.Value();
     nsCOMPtr<nsIInputStream> stream;
     nsAutoCString contentType;
     aRv = ExtractByteStreamFromBody(bodyInit,
                                     getter_AddRefs(stream), contentType);
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
--- a/dom/tests/mochitest/fetch/test_request.js
+++ b/dom/tests/mochitest/fetch/test_request.js
@@ -437,24 +437,39 @@ function testModeCorsPreflightEnumValue(
       invalidExc = e;
     }
     var expectedMessage = invalidExc.message.replace(invalidMode, 'cors-with-forced-preflight');
     is(e.message, expectedMessage,
        "mode cors-with-forced-preflight should throw same error as invalid RequestMode strings.");
   }
 }
 
+// HEAD/GET Requests are not allowed to have a body even when copying another
+// Request.
+function testBug1154268() {
+  var r1 = new Request("/index.html", { method: "POST", body: "Hi there" });
+  ["HEAD", "GET"].forEach(function(method) {
+    try {
+      var r2 = new Request(r1, { method: method });
+      ok(false, method + " Request copied from POST Request with body should fail.");
+    } catch (e) {
+      is(e.name, "TypeError", method + " Request copied from POST Request with body should fail.");
+    }
+  });
+}
+
 function runTest() {
   testDefaultCtor();
   testSimpleUrlParse();
   testUrlFragment();
   testMethod();
   testBug1109574();
   testHeaderGuard();
   testModeCorsPreflightEnumValue();
+  testBug1154268();
 
   return Promise.resolve()
     .then(testBodyCreation)
     .then(testBodyUsed)
     .then(testBodyExtraction)
     .then(testFormDataBodyCreation)
     .then(testFormDataBodyExtraction)
     .then(testUsedRequest)