author | Jon Droniak <droniakj1@owls.southernct.edu> |
Fri, 11 Sep 2015 11:26:33 -0700 | |
changeset 262105 | 4d3bfb6ffeb10bd68f8bdeed08121899d007e7cb |
parent 262104 | 4796f2a0cf56dea53edec64794ec5c0f724d4ac0 |
child 262106 | 757c4bd763261bc63a57ce9a4775406e67cbc85b |
push id | 29359 |
push user | philringnalda@gmail.com |
push date | Sat, 12 Sep 2015 15:57:02 +0000 |
treeherder | mozilla-central@cffdd225055e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | nsm |
bugs | 1199796 |
milestone | 43.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
|
--- a/dom/base/nsXMLHttpRequest.cpp +++ b/dom/base/nsXMLHttpRequest.cpp @@ -8,16 +8,17 @@ #ifndef XP_WIN #include <unistd.h> #endif #include "mozilla/ArrayUtils.h" #include "mozilla/CheckedInt.h" #include "mozilla/dom/BlobSet.h" #include "mozilla/dom/File.h" +#include "mozilla/dom/FetchUtil.h" #include "mozilla/dom/XMLHttpRequestUploadBinding.h" #include "mozilla/EventDispatcher.h" #include "mozilla/EventListenerManager.h" #include "mozilla/LoadInfo.h" #include "mozilla/MemoryReporting.h" #include "nsIDOMDocument.h" #include "mozilla/dom/ProgressEvent.h" #include "nsIJARChannel.h" @@ -1612,41 +1613,20 @@ nsXMLHttpRequest::Open(const nsACString& GetOwner()->GetExtantDoc()->WarnOnceAbout(nsIDocument::eSyncXMLHttpRequest); } Telemetry::Accumulate(Telemetry::XMLHTTPREQUEST_ASYNC_OR_SYNC, async ? 0 : 1); NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED); - // Disallow HTTP/1.1 TRACE method (see bug 302489) - // and MS IIS equivalent TRACK (see bug 381264) - // and CONNECT - if (inMethod.LowerCaseEqualsLiteral("trace") || - inMethod.LowerCaseEqualsLiteral("connect") || - inMethod.LowerCaseEqualsLiteral("track")) { - return NS_ERROR_DOM_SECURITY_ERR; - } - nsAutoCString method; - // GET, POST, DELETE, HEAD, OPTIONS, PUT methods normalized to upper case - if (inMethod.LowerCaseEqualsLiteral("get")) { - method.AssignLiteral("GET"); - } else if (inMethod.LowerCaseEqualsLiteral("post")) { - method.AssignLiteral("POST"); - } else if (inMethod.LowerCaseEqualsLiteral("delete")) { - method.AssignLiteral("DELETE"); - } else if (inMethod.LowerCaseEqualsLiteral("head")) { - method.AssignLiteral("HEAD"); - } else if (inMethod.LowerCaseEqualsLiteral("options")) { - method.AssignLiteral("OPTIONS"); - } else if (inMethod.LowerCaseEqualsLiteral("put")) { - method.AssignLiteral("PUT"); - } else { - method = inMethod; // other methods are not normalized + nsresult rv = FetchUtil::GetValidRequestMethod(inMethod, method); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; } // sync request is not allowed using withCredential or responseType // in window context if (!async && HasOrHasHadOwner() && (mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS || mTimeoutMilliseconds || mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT)) { @@ -1657,17 +1637,16 @@ nsXMLHttpRequest::Open(const nsACString& LogMessage("TimeoutSyncXHRWarning", GetOwner()); } if (mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT) { LogMessage("ResponseTypeSyncXHRWarning", GetOwner()); } return NS_ERROR_DOM_INVALID_ACCESS_ERR; } - nsresult rv; nsCOMPtr<nsIURI> uri; if (mState & (XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_HEADERS_RECEIVED | XML_HTTP_REQUEST_LOADING | XML_HTTP_REQUEST_SENT)) { // IE aborts as well Abort();
new file mode 100644 --- /dev/null +++ b/dom/fetch/FetchUtil.cpp @@ -0,0 +1,37 @@ +#include "FetchUtil.h" +#include "nsError.h" +#include "nsString.h" + +namespace mozilla { +namespace dom { + +// static +nsresult +FetchUtil::GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod) +{ + nsAutoCString upperCaseMethod(aMethod); + ToUpperCase(upperCaseMethod); + if (upperCaseMethod.EqualsLiteral("CONNECT") || + upperCaseMethod.EqualsLiteral("TRACE") || + upperCaseMethod.EqualsLiteral("TRACK") || + !NS_IsValidHTTPToken(aMethod)) { + outMethod.SetIsVoid(true); + return NS_ERROR_DOM_SECURITY_ERR; + } + + if (upperCaseMethod.EqualsLiteral("DELETE") || + upperCaseMethod.EqualsLiteral("GET") || + upperCaseMethod.EqualsLiteral("HEAD") || + upperCaseMethod.EqualsLiteral("OPTIONS") || + upperCaseMethod.EqualsLiteral("POST") || + upperCaseMethod.EqualsLiteral("PUT")) { + outMethod = upperCaseMethod; + } + else { + outMethod = aMethod; // Case unchanged for non-standard methods + } + return NS_OK; +} + +} // namespace dom +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/dom/fetch/FetchUtil.h @@ -0,0 +1,28 @@ +#ifndef mozilla_dom_FetchUtil_h +#define mozilla_dom_FetchUtil_h + +#include "nsString.h" +#include "nsError.h" + +namespace mozilla { +namespace dom { + +class FetchUtil final +{ +private: + FetchUtil() = delete; + +public: + /** + * Sets outMethod to a valid HTTP request method string based on an input method. + * Implements checks and normalization as specified by the Fetch specification. + * Returns NS_ERROR_DOM_SECURITY_ERR if the method is invalid. + * Otherwise returns NS_OK and the normalized method via outMethod. + */ + static nsresult + GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod); +}; + +} // namespace dom +} // namespace mozilla +#endif
--- a/dom/fetch/Request.cpp +++ b/dom/fetch/Request.cpp @@ -7,16 +7,17 @@ #include "Request.h" #include "nsIURI.h" #include "nsPIDOMWindow.h" #include "mozilla/ErrorResult.h" #include "mozilla/dom/Headers.h" #include "mozilla/dom/Fetch.h" +#include "mozilla/dom/FetchUtil.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/URL.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/workers/bindings/URL.h" #include "mozilla/unused.h" #include "WorkerPrivate.h" @@ -293,44 +294,31 @@ Request::Constructor(const GlobalObject& if (aInit.mRedirect.WasPassed()) { request->SetRedirectMode(aInit.mRedirect.Value()); } // Request constructor step 14. if (aInit.mMethod.WasPassed()) { nsAutoCString method(aInit.mMethod.Value()); - nsAutoCString upperCaseMethod = method; - ToUpperCase(upperCaseMethod); // Step 14.1. Disallow forbidden methods, and anything that is not a HTTP // token, since HTTP states that Method may be any of the defined values or // a token (extension method). - if (upperCaseMethod.EqualsLiteral("CONNECT") || - upperCaseMethod.EqualsLiteral("TRACE") || - upperCaseMethod.EqualsLiteral("TRACK") || - !NS_IsValidHTTPToken(method)) { + nsAutoCString outMethod; + nsresult rv = FetchUtil::GetValidRequestMethod(method, outMethod); + if (NS_FAILED(rv)) { NS_ConvertUTF8toUTF16 label(method); aRv.ThrowTypeError(MSG_INVALID_REQUEST_METHOD, &label); return nullptr; } // Step 14.2 - if (upperCaseMethod.EqualsLiteral("DELETE") || - upperCaseMethod.EqualsLiteral("GET") || - upperCaseMethod.EqualsLiteral("HEAD") || - upperCaseMethod.EqualsLiteral("POST") || - upperCaseMethod.EqualsLiteral("PUT") || - upperCaseMethod.EqualsLiteral("OPTIONS")) { - request->ClearCreatedByFetchEvent(); - request->SetMethod(upperCaseMethod); - } else { - request->ClearCreatedByFetchEvent(); - request->SetMethod(method); - } + request->ClearCreatedByFetchEvent(); + request->SetMethod(outMethod); } nsRefPtr<InternalHeaders> requestHeaders = request->Headers(); nsRefPtr<InternalHeaders> headers; if (aInit.mHeaders.WasPassed()) { nsRefPtr<Headers> h = Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv); if (aRv.Failed()) {
--- a/dom/fetch/moz.build +++ b/dom/fetch/moz.build @@ -3,28 +3,30 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS.mozilla.dom += [ 'ChannelInfo.h', 'Fetch.h', 'FetchDriver.h', + 'FetchUtil.h', 'Headers.h', 'InternalHeaders.h', 'InternalRequest.h', 'InternalResponse.h', 'Request.h', 'Response.h', ] UNIFIED_SOURCES += [ 'ChannelInfo.cpp', 'Fetch.cpp', 'FetchDriver.cpp', + 'FetchUtil.cpp', 'Headers.cpp', 'InternalHeaders.cpp', 'InternalRequest.cpp', 'InternalResponse.cpp', 'Request.cpp', 'Response.cpp', ]