diff options
-rw-r--r-- | browser/base/content/browser-media.js | 58 | ||||
-rw-r--r-- | browser/modules/ContentWebRTC.jsm | 1 | ||||
-rw-r--r-- | browser/modules/webrtcUI.jsm | 8 | ||||
-rw-r--r-- | chrome/nsChromeRegistry.cpp | 5 | ||||
-rw-r--r-- | dom/html/nsHTMLDocument.cpp | 12 | ||||
-rw-r--r-- | dom/media/GraphDriver.cpp | 1 | ||||
-rwxr-xr-x | dom/performance/PerformanceTiming.cpp | 8 | ||||
-rw-r--r-- | js/src/builtin/TypedArray.js | 75 | ||||
-rw-r--r-- | js/src/jit-test/tests/proxy/testWrapWithProtoIter.js | 1 | ||||
-rw-r--r-- | js/src/jit-test/tests/proxy/testWrapWithProtoTypedArray.js | 19 | ||||
-rw-r--r-- | mozglue/android/NSSBridge.cpp | 114 | ||||
-rw-r--r-- | mozglue/android/NSSBridge.h | 4 | ||||
-rw-r--r-- | netwerk/sctp/datachannel/DataChannel.cpp | 5 |
13 files changed, 165 insertions, 146 deletions
diff --git a/browser/base/content/browser-media.js b/browser/base/content/browser-media.js index f721be74d..bd5c5b227 100644 --- a/browser/base/content/browser-media.js +++ b/browser/base/content/browser-media.js @@ -45,11 +45,23 @@ var gEMEHandler = { } return true; }, - getLearnMoreLink: function(msgId) { - let text = gNavigatorBundle.getString("emeNotifications." + msgId + ".learnMoreLabel"); + getEMEDisabledFragment: function(msgId) { + let mainMessage = gNavigatorBundle.getString("emeNotifications.drmContentDisabled.message"); + let [prefix, suffix] = mainMessage.split(/%(?:\$\d)?S/).map(s => document.createTextNode(s)); + let text = gNavigatorBundle.getString("emeNotifications.drmContentDisabled.learnMoreLabel"); let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL"); - return "<label class='text-link' href='" + baseURL + "drm-content'>" + - text + "</label>"; + let link = document.createElement("label"); + link.className = "text-link"; + link.setAttribute("href", baseURL + "drm-content"); + link.textContent = text; + + let fragment = document.createDocumentFragment(); + [prefix, link, suffix].forEach(n => fragment.appendChild(n)); + return fragment; + }, + getMessageWithBrandName: function(notificationId) { + let msgId = "emeNotifications." + notificationId + ".message"; + return gNavigatorBundle.getFormattedString(msgId, [this._brandShortName]); }, receiveMessage: function({target: browser, data: data}) { let parsedData; @@ -67,7 +79,8 @@ var gEMEHandler = { let notificationId; let buttonCallback; - let params = []; + // Notification message can be either a string or a DOM fragment. + let notificationMessage; switch (status) { case "available": case "cdm-created": @@ -82,17 +95,17 @@ var gEMEHandler = { case "cdm-disabled": notificationId = "drmContentDisabled"; buttonCallback = gEMEHandler.ensureEMEEnabled.bind(gEMEHandler, browser, keySystem) - params = [this.getLearnMoreLink(notificationId)]; + notificationMessage = this.getEMEDisabledFragment(); break; case "cdm-insufficient-version": notificationId = "drmContentCDMInsufficientVersion"; - params = [this._brandShortName]; + notificationMessage = this.getMessageWithBrandName(notificationId); break; case "cdm-not-installed": notificationId = "drmContentCDMInstalling"; - params = [this._brandShortName]; + notificationMessage = this.getMessageWithBrandName(notificationId); break; case "cdm-not-supported": @@ -104,44 +117,29 @@ var gEMEHandler = { return; } - this.showNotificationBar(browser, notificationId, keySystem, params, buttonCallback); - }, - showNotificationBar: function(browser, notificationId, keySystem, labelParams, callback) { + // Now actually create the notification + let box = gBrowser.getNotificationBox(browser); if (box.getNotificationWithValue(notificationId)) { return; } - let msgPrefix = "emeNotifications." + notificationId + "."; - let msgId = msgPrefix + "message"; - - let message = labelParams.length ? - gNavigatorBundle.getFormattedString(msgId, labelParams) : - gNavigatorBundle.getString(msgId); - let buttons = []; - if (callback) { + if (buttonCallback) { + let msgPrefix = "emeNotifications." + notificationId + "."; let btnLabelId = msgPrefix + "button.label"; let btnAccessKeyId = msgPrefix + "button.accesskey"; buttons.push({ label: gNavigatorBundle.getString(btnLabelId), accessKey: gNavigatorBundle.getString(btnAccessKeyId), - callback: callback + callback: buttonCallback }); } let iconURL = "chrome://browser/skin/drm-icon.svg#chains-black"; - // Do a little dance to get rich content into the notification: - let fragment = document.createDocumentFragment(); - let descriptionContainer = document.createElement("description"); - descriptionContainer.innerHTML = message; - while (descriptionContainer.childNodes.length) { - fragment.appendChild(descriptionContainer.childNodes[0]); - } - - box.appendNotification(fragment, notificationId, iconURL, box.PRIORITY_WARNING_MEDIUM, - buttons); + box.appendNotification(notificationMessage, notificationId, iconURL, + box.PRIORITY_WARNING_MEDIUM, buttons); }, showPopupNotificationForSuccess: function(browser, keySystem) { // We're playing EME content! Remove any "we can't play because..." messages. diff --git a/browser/modules/ContentWebRTC.jsm b/browser/modules/ContentWebRTC.jsm index bfb98a868..fd50176a0 100644 --- a/browser/modules/ContentWebRTC.jsm +++ b/browser/modules/ContentWebRTC.jsm @@ -208,6 +208,7 @@ function prompt(aContentWindow, aWindowID, aCallID, aConstraints, aDevices, aSec let request = { callID: aCallID, windowID: aWindowID, + origin: aContentWindow.origin, documentURI: aContentWindow.document.documentURI, secure: aSecure, requestTypes: requestTypes, diff --git a/browser/modules/webrtcUI.jsm b/browser/modules/webrtcUI.jsm index b24135bfc..08de46bb3 100644 --- a/browser/modules/webrtcUI.jsm +++ b/browser/modules/webrtcUI.jsm @@ -290,7 +290,13 @@ function prompt(aBrowser, aRequest) { let {audioDevices: audioDevices, videoDevices: videoDevices, sharingScreen: sharingScreen, sharingAudio: sharingAudio, requestTypes: requestTypes} = aRequest; - let uri = Services.io.newURI(aRequest.documentURI, null, null); + let uri; + try { + // This fails for principals that serialize to "null", e.g. file URIs. + uri = Services.io.newURI(aRequest.origin, null, null); + } catch (e) { + uri = Services.io.newURI(aRequest.documentURI, null, null); + } let host = getHost(uri); let chromeDoc = aBrowser.ownerDocument; let chromeWin = chromeDoc.defaultView; diff --git a/chrome/nsChromeRegistry.cpp b/chrome/nsChromeRegistry.cpp index 0aa7f3f14..0302b9997 100644 --- a/chrome/nsChromeRegistry.cpp +++ b/chrome/nsChromeRegistry.cpp @@ -234,15 +234,18 @@ nsChromeRegistry::Canonify(nsIURL* aChromeURL) aChromeURL->SetPath(path); } else { - // prevent directory traversals ("..") // path is already unescaped once, but uris can get unescaped twice const char* pos = path.BeginReading(); const char* end = path.EndReading(); + if (*pos == '/' || *pos == ' ') { + return NS_ERROR_DOM_BAD_URI; + } while (pos < end) { switch (*pos) { case ':': return NS_ERROR_DOM_BAD_URI; case '.': + // prevent directory traversals ("..") if (pos[1] == '.') return NS_ERROR_DOM_BAD_URI; break; diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp index fea78dc37..be5a34d41 100644 --- a/dom/html/nsHTMLDocument.cpp +++ b/dom/html/nsHTMLDocument.cpp @@ -1536,6 +1536,18 @@ nsHTMLDocument::Open(JSContext* cx, nsCOMPtr<nsIDocument> ret = this; return ret.forget(); } + + // Now double-check that our invariants still hold. + if (!mScriptGlobalObject) { + nsCOMPtr<nsIDocument> ret = this; + return ret.forget(); + } + + nsPIDOMWindowOuter* outer = GetWindow(); + if (!outer || (GetInnerWindow() != outer->GetCurrentInnerWindow())) { + nsCOMPtr<nsIDocument> ret = this; + return ret.forget(); + } } nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(shell)); diff --git a/dom/media/GraphDriver.cpp b/dom/media/GraphDriver.cpp index 9b74bd58c..40e3b72cf 100644 --- a/dom/media/GraphDriver.cpp +++ b/dom/media/GraphDriver.cpp @@ -1055,6 +1055,7 @@ AudioCallbackDriver::StateCallback(cubeb_state aState) { STREAM_LOG(LogLevel::Debug, ("AudioCallbackDriver State: %d", aState)); if (aState == CUBEB_STATE_ERROR && mShouldFallbackIfError) { + mShouldFallbackIfError = false; MonitorAutoLock lock(GraphImpl()->GetMonitor()); // Fall back to a driver using a normal thread. If needed, // the graph will try to re-open an audio stream later. diff --git a/dom/performance/PerformanceTiming.cpp b/dom/performance/PerformanceTiming.cpp index 97bbcb0ca..5f771f0aa 100755 --- a/dom/performance/PerformanceTiming.cpp +++ b/dom/performance/PerformanceTiming.cpp @@ -307,12 +307,8 @@ PerformanceTiming::SecureConnectionStartHighRes() if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } - - // Round down to the nearest 1ms - const double maxResolutionMs = 1; - return mSecureConnectionStart.IsNull() - ? mZeroTime - : floor(TimeStampToDOMHighRes(mSecureConnectionStart) / maxResolutionMs) * maxResolutionMs; + return mSecureConnectionStart.IsNull() ? mZeroTime + : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mSecureConnectionStart)); } DOMTimeMilliSec diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js index 4d2d6488f..4a3f38365 100644 --- a/js/src/builtin/TypedArray.js +++ b/js/src/builtin/TypedArray.js @@ -35,6 +35,10 @@ function IsDetachedBuffer(buffer) { return (flags & JS_ARRAYBUFFER_DETACHED_FLAG) !== 0; } +function TypedArrayLengthMethod() { + return TypedArrayLength(this); +} + function GetAttachedArrayBuffer(tarray) { var buffer = ViewedArrayBufferIfReified(tarray); if (IsDetachedBuffer(buffer)) @@ -42,6 +46,10 @@ function GetAttachedArrayBuffer(tarray) { return buffer; } +function GetAttachedArrayBufferMethod() { + return GetAttachedArrayBuffer(this); +} + // A function which ensures that the argument is either a typed array or a // cross-compartment wrapper for a typed array and that the typed array involved // has an attached array buffer. If one of those conditions doesn't hold (wrong @@ -54,10 +62,7 @@ function IsTypedArrayEnsuringArrayBuffer(arg) { return true; } - // This is a bit hacky but gets the job done: the first `arg` is used to - // test for a wrapped typed array, the second as an argument to - // GetAttachedArrayBuffer. - callFunction(CallTypedArrayMethodIfWrapped, arg, arg, "GetAttachedArrayBuffer"); + callFunction(CallTypedArrayMethodIfWrapped, arg, "GetAttachedArrayBufferMethod"); return false; } @@ -98,8 +103,8 @@ function TypedArrayCreateWithLength(constructor, length) { if (isTypedArray) { len = TypedArrayLength(newTypedArray); } else { - len = callFunction(CallTypedArrayMethodIfWrapped, newTypedArray, newTypedArray, - "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, newTypedArray, + "TypedArrayLengthMethod"); } if (len < length) @@ -259,15 +264,14 @@ function TypedArrayEvery(callbackfn/*, thisArg*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Steps 3-5. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 6. if (arguments.length === 0) @@ -348,15 +352,14 @@ function TypedArrayFilter(callbackfn/*, thisArg*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 4. if (arguments.length === 0) @@ -410,15 +413,14 @@ function TypedArrayFind(predicate/*, thisArg*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Steps 3-5. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 6. if (arguments.length === 0) @@ -452,15 +454,14 @@ function TypedArrayFindIndex(predicate/*, thisArg*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Steps 3-5. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 6. if (arguments.length === 0) @@ -492,15 +493,14 @@ function TypedArrayForEach(callbackfn/*, thisArg*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Step 3-4. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 5. if (arguments.length === 0) @@ -686,15 +686,14 @@ function TypedArrayMap(callbackfn/*, thisArg*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Step 3. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 4. if (arguments.length === 0) @@ -730,15 +729,14 @@ function TypedArrayReduce(callbackfn/*, initialValue*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Steps 3-5. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 6. if (arguments.length === 0) @@ -776,15 +774,14 @@ function TypedArrayReduceRight(callbackfn/*, initialValue*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Steps 3-5. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 6. if (arguments.length === 0) @@ -1034,15 +1031,14 @@ function TypedArraySome(callbackfn/*, thisArg*/) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(O); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Steps 3-5. var len; if (isTypedArray) len = TypedArrayLength(O); else - len = callFunction(CallTypedArrayMethodIfWrapped, O, O, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); // Step 6. if (arguments.length === 0) @@ -1137,7 +1133,7 @@ function TypedArraySort(comparefn) { if (isTypedArray) { buffer = GetAttachedArrayBuffer(obj); } else { - buffer = callFunction(CallTypedArrayMethodIfWrapped, obj, obj, "GetAttachedArrayBuffer"); + buffer = callFunction(CallTypedArrayMethodIfWrapped, obj, "GetAttachedArrayBufferMethod"); } // Step 3. @@ -1145,7 +1141,7 @@ function TypedArraySort(comparefn) { if (isTypedArray) { len = TypedArrayLength(obj); } else { - len = callFunction(CallTypedArrayMethodIfWrapped, obj, obj, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, obj, "TypedArrayLengthMethod"); } if (comparefn === undefined) { @@ -1181,8 +1177,8 @@ function TypedArraySort(comparefn) { if (isTypedArray) { buffer = GetAttachedArrayBuffer(obj); } else { - buffer = callFunction(CallTypedArrayMethodIfWrapped, obj, obj, - "GetAttachedArrayBuffer"); + buffer = callFunction(CallTypedArrayMethodIfWrapped, obj, + "GetAttachedArrayBufferMethod"); } } var bufferDetached; @@ -1217,15 +1213,14 @@ function TypedArrayToLocaleString(locales = undefined, options = undefined) { // We want to make sure that we have an attached buffer, per spec prose. var isTypedArray = IsTypedArrayEnsuringArrayBuffer(array); - // If we got here, `this` is either a typed array or a cross-compartment - // wrapper for one. + // If we got here, `this` is either a typed array or a wrapper for one. // Step 2. var len; if (isTypedArray) len = TypedArrayLength(array); else - len = callFunction(CallTypedArrayMethodIfWrapped, array, array, "TypedArrayLength"); + len = callFunction(CallTypedArrayMethodIfWrapped, array, "TypedArrayLengthMethod"); // Step 4. if (len === 0) diff --git a/js/src/jit-test/tests/proxy/testWrapWithProtoIter.js b/js/src/jit-test/tests/proxy/testWrapWithProtoIter.js new file mode 100644 index 000000000..c6854b206 --- /dev/null +++ b/js/src/jit-test/tests/proxy/testWrapWithProtoIter.js @@ -0,0 +1 @@ +[...wrapWithProto(new Int8Array(), new Int8Array())] diff --git a/js/src/jit-test/tests/proxy/testWrapWithProtoTypedArray.js b/js/src/jit-test/tests/proxy/testWrapWithProtoTypedArray.js new file mode 100644 index 000000000..1b805d30a --- /dev/null +++ b/js/src/jit-test/tests/proxy/testWrapWithProtoTypedArray.js @@ -0,0 +1,19 @@ +let a = wrapWithProto(new Int8Array([1, 3, 5, 6, 9]), new Int8Array()); + +assertEq([...a].toString(), "1,3,5,6,9"); +assertEq(a.every(e => e < 100), true); +assertEq(a.filter(e => e % 2 == 1).toString(), "1,3,5,9"); +assertEq(a.find(e => e > 3), 5); +assertEq(a.findIndex(e => e % 2 == 0), 3); +assertEq(a.map(e => e * 10).toString(), "10,30,50,60,90"); +assertEq(a.reduce((a, b) => a + b, ""), "13569"); +assertEq(a.reduceRight((acc, e) => "(" + e + acc + ")", ""), "(1(3(5(6(9)))))"); +assertEq(a.some(e => e % 2 == 0), true); + +let s = ""; +assertEq(a.forEach(e => s += e), undefined); +assertEq(s, "13569"); + +a.sort((a, b) => b - a); +assertEq(a.toString(), "9,6,5,3,1"); + diff --git a/mozglue/android/NSSBridge.cpp b/mozglue/android/NSSBridge.cpp index 2a9b5771d..3343ad1b2 100644 --- a/mozglue/android/NSSBridge.cpp +++ b/mozglue/android/NSSBridge.cpp @@ -37,6 +37,10 @@ NSS_WRAPPER_INT(PL_Base64Encode) NSS_WRAPPER_INT(PL_Base64Decode) NSS_WRAPPER_INT(PL_strfree) +SECStatus doCrypto(JNIEnv* jenv, const char *path, const char *value, char** result, bool doEncrypt); +SECStatus encode(const uint8_t* data, uint32_t srclen, char** result); +SECStatus decode(const char* data, uint8_t** result, uint32_t* length); + int setup_nss_functions(void *nss_handle, void *nspr_handle, @@ -189,41 +193,40 @@ doCrypto(JNIEnv* jenv, const char *path, const char *value, char** result, bool keyid.len = 0; rv = f_PK11SDR_Encrypt(&keyid, &request, &reply, nullptr); - if (rv != SECSuccess) { + if (rv == SECSuccess) { + rv = encode(reply.data, reply.len, result); + if (rv == SECSuccess) { + LOG("Encrypted: %s\n", *result); + } else { + throwError(jenv, "encode"); + } + } else { throwError(jenv, "PK11SDR_Encrypt"); - goto done; } - rv = encode(reply.data, reply.len, result); - if (rv != SECSuccess) { - throwError(jenv, "encode"); - goto done; - } - LOG("Encrypted: %s\n", *result); } else { LOG("Decoding: %s\n", value); - rv = decode(value, &request.data, (int32_t*)&request.len); + rv = decode(value, &request.data, &request.len); if (rv != SECSuccess) { throwError(jenv, "decode"); return rv; } rv = f_PK11SDR_Decrypt(&request, &reply, nullptr); - if (rv != SECSuccess) { - throwError(jenv, "PK11SDR_Decrypt"); - goto done; - } - *result = (char *)malloc(reply.len+1); - strncpy(*result, (char *)reply.data, reply.len); - (*result)[reply.len] = '\0'; + if (rv == SECSuccess) { + *result = static_cast<char*>(malloc(reply.len + 1)); + strncpy(*result, reinterpret_cast<char*>(reply.data), reply.len); + (*result)[reply.len] = '\0'; - // This can print sensitive data. Uncomment if you need it. - // LOG("Decoded %i letters: %s\n", reply.len, *result); + // This can print sensitive data. Uncomment if you need it. + // LOG("Decoded %i letters: %s\n", reply.len, *result); + } else { + throwError(jenv, "PK11SDR_Decrypt"); + } free(request.data); } -done: f_SECITEM_ZfreeItem(&reply, false); return rv; } @@ -232,64 +235,51 @@ done: * Base64 encodes the data passed in. The caller must deallocate _retval using free(); */ SECStatus -encode(const unsigned char *data, int32_t dataLen, char **_retval) +encode(const uint8_t* data, uint32_t srclen, char** result) { - SECStatus rv = SECSuccess; - char *encoded = f_PL_Base64Encode((const char *)data, dataLen, nullptr); - if (!encoded) - rv = SECFailure; - if (!*encoded) - rv = SECFailure; - - if (rv == SECSuccess) { - *_retval = (char *)malloc(strlen(encoded)+1); - strcpy(*_retval, encoded); + if (srclen > (PR_UINT32_MAX / 4) * 3) { + return SECFailure; } - if (encoded) { - f_PR_Free(encoded); + const uint32_t dstlen = ((srclen + 2) / 3) * 4; + char* const buffer = static_cast<char*>(malloc(dstlen + 1)); + + if (!buffer || !f_PL_Base64Encode(reinterpret_cast<const char*>(data), srclen, buffer)) { + free(buffer); + *result = nullptr; + return SECFailure; } - return rv; + buffer[dstlen] = '\0'; + *result = buffer; + return SECSuccess; } /* * Base64 decodes the data passed in. The caller must deallocate result using free(); */ SECStatus -decode(const char *data, unsigned char **result, int32_t *length) +decode(const char* data, uint8_t** result, uint32_t* length) { - SECStatus rv = SECSuccess; - uint32_t len = strlen(data); - int adjust = 0; - - /* Compute length adjustment */ - if (len > 0 && data[len-1] == '=') { - adjust++; - if (data[len-2] == '=') adjust++; + uint32_t srclen = strlen(data); + while (srclen && data[srclen - 1] == '=') { + srclen--; } - char *decoded; - decoded = f_PL_Base64Decode(data, len, nullptr); - if (!decoded) { - return SECFailure; - } - if (!*decoded) { + // Avoid overflow when calculating result length. + const uint32_t dstlen = (srclen / 4) * 3 + ((srclen % 4) * 3) / 4; + // At most 2 extra bytes due to padding in input. + uint8_t* const buffer = static_cast<uint8_t*>(malloc(dstlen + 2)); + + if (!buffer || !f_PL_Base64Decode(data, srclen, reinterpret_cast<char*>(buffer))) { + free(buffer); + *result = nullptr; + *length = 0; return SECFailure; } - *length = (len*3)/4 - adjust; - LOG("Decoded %i chars into %i chars\n", len, *length); - - *result = (unsigned char*)malloc((size_t)len); - - if (!*result) { - rv = SECFailure; - } else { - memcpy((char*)*result, decoded, len); - } - f_PR_Free(decoded); - return rv; + buffer[dstlen] = '\0'; + *result = buffer; + *length = dstlen; + return SECSuccess; } - - diff --git a/mozglue/android/NSSBridge.h b/mozglue/android/NSSBridge.h index 77bcd1172..83ec8d749 100644 --- a/mozglue/android/NSSBridge.h +++ b/mozglue/android/NSSBridge.h @@ -39,8 +39,4 @@ NSS_WRAPPER(PK11_GetInternalKeySlot, PK11SlotInfo *, void) NSS_WRAPPER(PK11_NeedUserInit, PRBool, PK11SlotInfo *) NSS_WRAPPER(PK11_InitPin, SECStatus, PK11SlotInfo*, const char*, const char*) -bool setPassword(PK11SlotInfo *slot); -SECStatus doCrypto(JNIEnv* jenv, const char *path, const char *value, char** result, bool doEncrypt); -SECStatus encode(const unsigned char *data, int32_t dataLen, char **_retval); -SECStatus decode(const char *data, unsigned char **result, int32_t * _retval); #endif /* NSS_h */ diff --git a/netwerk/sctp/datachannel/DataChannel.cpp b/netwerk/sctp/datachannel/DataChannel.cpp index bf7790f51..d47a9d5ea 100644 --- a/netwerk/sctp/datachannel/DataChannel.cpp +++ b/netwerk/sctp/datachannel/DataChannel.cpp @@ -646,6 +646,7 @@ DataChannelConnection::SctpDtlsInput(TransportFlow *flow, } } // Pass the data to SCTP + MutexAutoLock lock(mLock); usrsctp_conninput(static_cast<void *>(this), data, len, 0); } @@ -1016,7 +1017,7 @@ DataChannelConnection::SendDeferredMessages() bool still_blocked = false; // This may block while something is modifying channels, but should not block for IO - MutexAutoLock lock(mLock); + mLock.AssertCurrentThreadOwns(); // XXX For total fairness, on a still_blocked we'd start next time at the // same index. Sorry, not going to bother for now. @@ -1923,7 +1924,7 @@ DataChannelConnection::ReceiveCallback(struct socket* sock, void *data, size_t d if (!data) { usrsctp_close(sock); // SCTP has finished shutting down } else { - MutexAutoLock lock(mLock); + mLock.AssertCurrentThreadOwns(); if (flags & MSG_NOTIFICATION) { HandleNotification(static_cast<union sctp_notification *>(data), datalen); } else { |