diff --git a/gfx/2d/FilterNodeSoftware.cpp b/gfx/2d/FilterNodeSoftware.cpp index 1696940698..09e5845cbf 100644 --- a/gfx/2d/FilterNodeSoftware.cpp +++ b/gfx/2d/FilterNodeSoftware.cpp @@ -2443,8 +2443,11 @@ FilterNodeConvolveMatrixSoftware::DoRender(const IntRect& aRect, CoordType aKernelUnitLengthX, CoordType aKernelUnitLengthY) { + // Ensure multiply fits in an int32_t so convolve math won't overflow. + auto kernelArea = CheckedInt32(mKernelSize.width) * mKernelSize.height; if (mKernelSize.width <= 0 || mKernelSize.height <= 0 || - mKernelMatrix.size() != uint32_t(mKernelSize.width * mKernelSize.height) || + !kernelArea.isValid() || + mKernelMatrix.size() != size_t(kernelArea.value()) || !IntRect(IntPoint(0, 0), mKernelSize).Contains(mTarget) || mDivisor == 0) { return Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8, true); diff --git a/gfx/thebes/gfxHarfBuzzShaper.cpp b/gfx/thebes/gfxHarfBuzzShaper.cpp index 7f05f9011f..4103cdaaac 100644 --- a/gfx/thebes/gfxHarfBuzzShaper.cpp +++ b/gfx/thebes/gfxHarfBuzzShaper.cpp @@ -1155,8 +1155,8 @@ AddOpenTypeFeature(const uint32_t& aTag, uint32_t& aValue, void *aUserArg) * gfxFontShaper override to initialize the text run using HarfBuzz */ -static hb_font_funcs_t * sHBFontFuncs = nullptr; -static hb_unicode_funcs_t * sHBUnicodeFuncs = nullptr; +static hb_font_funcs_t* sHBFontFuncs = nullptr; +static hb_unicode_funcs_t* sHBUnicodeFuncs = nullptr; static const hb_script_t sMathScript = hb_ot_tag_to_script(HB_TAG('m','a','t','h')); @@ -1171,55 +1171,61 @@ gfxHarfBuzzShaper::Initialize() mUseFontGlyphWidths = mFont->ProvidesGlyphWidths(); - if (!sHBFontFuncs) { - // static function callback pointers, initialized by the first - // harfbuzz shaper used - sHBFontFuncs = hb_font_funcs_create(); - hb_font_funcs_set_nominal_glyph_func(sHBFontFuncs, + // Function callback pointers; these are local statics to ensure thread-safe + // initialization on first use. + static hb_font_funcs_t* sHBFontFuncs = [] { + auto* funcs = hb_font_funcs_create(); + hb_font_funcs_set_nominal_glyph_func(funcs, HBGetNominalGlyph, nullptr, nullptr); - hb_font_funcs_set_variation_glyph_func(sHBFontFuncs, + hb_font_funcs_set_variation_glyph_func(funcs, HBGetVariationGlyph, nullptr, nullptr); - hb_font_funcs_set_glyph_h_advance_func(sHBFontFuncs, + hb_font_funcs_set_glyph_h_advance_func(funcs, HBGetGlyphHAdvance, nullptr, nullptr); - hb_font_funcs_set_glyph_v_advance_func(sHBFontFuncs, + hb_font_funcs_set_glyph_v_advance_func(funcs, HBGetGlyphVAdvance, nullptr, nullptr); - hb_font_funcs_set_glyph_v_origin_func(sHBFontFuncs, + hb_font_funcs_set_glyph_v_origin_func(funcs, HBGetGlyphVOrigin, nullptr, nullptr); - hb_font_funcs_set_glyph_extents_func(sHBFontFuncs, + hb_font_funcs_set_glyph_extents_func(funcs, HBGetGlyphExtents, nullptr, nullptr); - hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs, + hb_font_funcs_set_glyph_contour_point_func(funcs, HBGetContourPoint, nullptr, nullptr); - hb_font_funcs_set_glyph_h_kerning_func(sHBFontFuncs, + hb_font_funcs_set_glyph_h_kerning_func(funcs, HBGetHKerning, nullptr, nullptr); + return funcs; + }(); - sHBUnicodeFuncs = - hb_unicode_funcs_create(hb_unicode_funcs_get_empty()); - hb_unicode_funcs_set_mirroring_func(sHBUnicodeFuncs, + static hb_unicode_funcs_t* sHBUnicodeFuncs = [] { + auto* funcs = hb_unicode_funcs_create(hb_unicode_funcs_get_empty()); + hb_unicode_funcs_set_mirroring_func(funcs, HBGetMirroring, nullptr, nullptr); - hb_unicode_funcs_set_script_func(sHBUnicodeFuncs, HBGetScript, + hb_unicode_funcs_set_script_func(funcs, + HBGetScript, nullptr, nullptr); - hb_unicode_funcs_set_general_category_func(sHBUnicodeFuncs, + hb_unicode_funcs_set_general_category_func(funcs, HBGetGeneralCategory, nullptr, nullptr); - hb_unicode_funcs_set_combining_class_func(sHBUnicodeFuncs, + hb_unicode_funcs_set_combining_class_func(funcs, HBGetCombiningClass, nullptr, nullptr); - hb_unicode_funcs_set_compose_func(sHBUnicodeFuncs, + hb_unicode_funcs_set_compose_func(funcs, HBUnicodeCompose, nullptr, nullptr); - hb_unicode_funcs_set_decompose_func(sHBUnicodeFuncs, + hb_unicode_funcs_set_decompose_func(funcs, HBUnicodeDecompose, nullptr, nullptr); - + return funcs; + }(); + + if (!sNormalizer) { UErrorCode error = U_ZERO_ERROR; sNormalizer = unorm2_getNFCInstance(&error); MOZ_ASSERT(U_SUCCESS(error), "failed to get ICU normalizer"); diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js index 9c22c51f2c..16603d9b86 100644 --- a/js/src/builtin/TypedArray.js +++ b/js/src/builtin/TypedArray.js @@ -899,6 +899,73 @@ function TypedArrayToReversed() { return A; } +// ES2023 23.2.3.33 %TypedArray%.prototype.toSorted ( comparator ) +function TypedArrayToSorted(comparator) { + // Step 1. + if (comparator !== undefined && !IsCallable(comparator)) + ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, comparator)); + + // Step 2. + var O = this; + + // Step 3. + // This function is not generic. + // 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 wrapper for one. + + // Step 4. + var len; + if (isTypedArray) + len = TypedArrayLength(O); + else + len = callFunction(CallTypedArrayMethodIfWrapped, O, "TypedArrayLengthMethod"); + + // Step 5. + var A = TypedArrayCreateSameType(O, len); + + // Step 8. + var sortedList = new List(); + for (var k = 0; k < len; k++) { + sortedList[k] = O[k]; + } + + if (len > 1) { + // Steps 6-7. + var sortCompare; + if (comparator === undefined) { + var isBigIntContentType; + if (isTypedArray) { + isBigIntContentType = callFunction(TypedArrayContentTypeIsBigIntMethod, O); + } else { + isBigIntContentType = callFunction(CallTypedArrayMethodIfWrapped, O, + "TypedArrayContentTypeIsBigIntMethod"); + } + sortCompare = isBigIntContentType ? TypedArrayCompareBigInt : TypedArrayCompare; + } else { + var wrappedComparator = comparator; + sortCompare = function(x, y) { + // CompareTypedArrayElements step 2.a. + var v = ToNumber(callContentFunction(wrappedComparator, undefined, x, y)); + + // CompareTypedArrayElements step 2.b. + return Number_isNaN(v) ? 0 : v; + }; + } + + MergeSort(sortedList, len, sortCompare); + } + + // Steps 9-10. + for (var j = 0; j < len; j++) { + A[j] = sortedList[j]; + } + + // Step 11. + return A; +} + // ES2023 23.2.3.36 %TypedArray%.prototype.with ( index, value ) function TypedArrayWith(index, value) { // Step 1. diff --git a/js/src/tests/ecma_6/TypedArray/toSorted.js b/js/src/tests/ecma_6/TypedArray/toSorted.js new file mode 100644 index 0000000000..ad19f2fb50 --- /dev/null +++ b/js/src/tests/ecma_6/TypedArray/toSorted.js @@ -0,0 +1,119 @@ +for (var constructor of anyTypedArrayConstructors) { + assertEq(constructor.prototype.toSorted.length, 1); + + var original = new constructor([3, 1, 2]); + var sorted = original.toSorted(); + assertDeepEq(sorted, new constructor([1, 2, 3])); + assertDeepEq(original, new constructor([3, 1, 2])); + assertEq(sorted === original, false); + assertEq(sorted.constructor, constructor); + + var descending = original.toSorted((a, b) => b - a); + assertDeepEq(descending, new constructor([3, 2, 1])); + assertDeepEq(original, new constructor([3, 1, 2])); + + var stableInput = new constructor([2, 1, 4, 3]); + var stableSorted = stableInput.toSorted((a, b) => (a % 2) - (b % 2)); + assertDeepEq(stableSorted, new constructor([2, 4, 1, 3])); + + var nanComparatorInput = new constructor([4, 1, 3, 2]); + var nanComparatorSorted = nanComparatorInput.toSorted(() => NaN); + assertDeepEq(nanComparatorSorted, nanComparatorInput); + + var ctorIgnored = new constructor([5, 1, 4]); + Object.defineProperty(ctorIgnored, "constructor", { + get() { + throw new Error("constructor accessor called"); + } + }); + assertDeepEq(ctorIgnored.toSorted(), new constructor([1, 4, 5])); + + if (isFloatConstructor(constructor)) { + var floatInput = new constructor([0, -0, 1, -1, NaN]); + var floatSorted = floatInput.toSorted(); + + assertEq(floatSorted[0], -1); + assertEq(1 / floatSorted[1], -Infinity); + assertEq(1 / floatSorted[2], Infinity); + assertEq(floatSorted[3], 1); + assertEq(Number.isNaN(floatSorted[4]), true); + } + + var invalidReceivers = [undefined, null, 1, false, "", Symbol(), [], {}, /./, + new Proxy(new constructor(), {})]; + invalidReceivers.forEach(invalidReceiver => { + assertThrowsInstanceOf(() => { + constructor.prototype.toSorted.call(invalidReceiver); + }, TypeError, + "Assert that toSorted fails if this value is not a TypedArray"); + }); +} + +for (var constructor of typedArrayConstructors) { + if (typeof newGlobal === "function") { + var toSorted = newGlobal()[constructor.name].prototype.toSorted; + var original = new constructor([3, 2, 1]); + var sorted = toSorted.call(original); + + assertDeepEq(sorted, new constructor([1, 2, 3])); + assertDeepEq(original, new constructor([3, 2, 1])); + } +} + +assertThrowsInstanceOf(() => { + Int32Array.prototype.toSorted.call(new Int32Array([1, 2, 3]), 0); +}, TypeError); + +if (typeof detachArrayBuffer === "function") { + assertThrowsInstanceOf(() => { + let buffer = new ArrayBuffer(16); + let array = new Int32Array(buffer); + detachArrayBuffer(buffer); + array.toSorted(); + }, TypeError); +} + +if (typeof detachArrayBuffer === "function") { + let ta = new Int32Array([3, 1, 2]); + let detached = false; + let sorted = ta.toSorted(function(a, b) { + if (!detached) { + detached = true; + detachArrayBuffer(ta.buffer); + } + return a - b; + }); + assertDeepEq(sorted, new Int32Array([1, 2, 3])); +} + +if (typeof newGlobal === "function" && typeof detachArrayBuffer === "function") { + let ta = new Int32Array([3, 1, 2]); + let otherGlobal = newGlobal(); + let detached = false; + let sorted = otherGlobal.Int32Array.prototype.toSorted.call(ta, function(a, b) { + if (!detached) { + detached = true; + detachArrayBuffer(ta.buffer); + } + return a - b; + }); + assertDeepEq(sorted, new Int32Array([1, 2, 3])); +} + +if (typeof BigInt64Array === "function" && typeof BigUint64Array === "function") { + let bigIntArray = new BigInt64Array([3n, 1n, 2n]); + let bigIntSorted = bigIntArray.toSorted(); + assertEq(BigInt64Array.prototype.toSorted.length, 1); + assertDeepEq(bigIntSorted, new BigInt64Array([1n, 2n, 3n])); + assertDeepEq(bigIntArray, new BigInt64Array([3n, 1n, 2n])); + + assertThrowsInstanceOf(() => { + bigIntArray.toSorted((a, b) => a - b); + }, TypeError); + + let bigUintArray = new BigUint64Array([3n, 1n, 2n]); + assertDeepEq(bigUintArray.toSorted(), new BigUint64Array([1n, 2n, 3n])); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index fd687946ca..b04ebcf291 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -1629,6 +1629,7 @@ TypedArrayObject::protoFunctions[] = { JS_SELF_HOSTED_FN("reduceRight", "TypedArrayReduceRight", 1, 0), JS_SELF_HOSTED_FN("reverse", "TypedArrayReverse", 0, 0), JS_SELF_HOSTED_FN("toReversed", "TypedArrayToReversed", 0, 0), + JS_SELF_HOSTED_FN("toSorted", "TypedArrayToSorted", 1, 0), JS_SELF_HOSTED_FN("with", "TypedArrayWith", 2, 0), JS_SELF_HOSTED_FN("slice", "TypedArraySlice", 2, 0), JS_SELF_HOSTED_FN("some", "TypedArraySome", 1, 0), diff --git a/media/webrtc/trunk/build/mac/find_sdk_uxp.py b/media/webrtc/trunk/build/mac/find_sdk_uxp.py index 4d0cac51a6..6a84fdd7c2 100644 --- a/media/webrtc/trunk/build/mac/find_sdk_uxp.py +++ b/media/webrtc/trunk/build/mac/find_sdk_uxp.py @@ -19,11 +19,14 @@ if sys.platform == 'darwin': print("find_sdk_uxp.py: error: Specified path does not exist or is not a directory") sys.exit(1) - KNOWN_SDK_VERSIONS = ["10.7", "10.8", "10.9", "10.10", "10.11" - "10.12", "10.13", "10.14", "10.15", "10.16", - "11.0", "11.1", "11.2", "11.3", "12.0", "12.1", "12.3", - "13.0", "13.1", "13.2", "14.0", "14.2", "14.4", "14.5", - "15.0", "15.1", "15.2", "15.4"] + KNOWN_SDK_VERSIONS = ["10.4", "10.5", "10.6", "10.7", "10.8", "10.9", "10.10", + "10.11", "10.12", "10.13", "10.14", "10.15", "10.16", + "11.0", "11.1", "11.2", "11.3", + "12.0", "12.1", "12.3", + "13.0", "13.1", "13.2", + "14.0", "14.2", "14.4", "14.5", + "15.0", "15.1", "15.2", "15.4", + "26.0", "26.1", "26.4"] REGEX = "^MacOSX(\d+\.\d+)\.sdk$" SDK_VERSION = re.findall(REGEX, os.path.basename(SDK_PATH)) diff --git a/netwerk/protocol/http/nsHttpResponseHead.cpp b/netwerk/protocol/http/nsHttpResponseHead.cpp index 4c3c2cd639..0f0a64e7b8 100644 --- a/netwerk/protocol/http/nsHttpResponseHead.cpp +++ b/netwerk/protocol/http/nsHttpResponseHead.cpp @@ -625,10 +625,13 @@ nsHttpResponseHead::ParseHeaderLine_locked(const nsACString &line, bool original LOG(("invalid content-length! %s\n", val.get())); } } else if (hdr == nsHttp::Content_Type) { - LOG(("ParseContentType [type=%s]\n", val.get())); - bool dummy; - net_ParseContentType(val, - mContentType, mContentCharset, &dummy); + if (mStatus == 304) { + LOG(("Non-compliant Content-type value ignored")); + } else { + LOG(("ParseContentType [type=%s]\n", val.get())); + bool dummy; + net_ParseContentType(val, mContentType, mContentCharset, &dummy); + } } else if (hdr == nsHttp::Cache_Control) { // Re-parse merged header in its entirety. See Issue #2852 ParseCacheControl(mHeaders.PeekHeader(hdr)); diff --git a/security/nss/lib/pk11wrap/pk11pk12.c b/security/nss/lib/pk11wrap/pk11pk12.c index 360c03bd40..4f8f9d2518 100644 --- a/security/nss/lib/pk11wrap/pk11pk12.c +++ b/security/nss/lib/pk11wrap/pk11pk12.c @@ -286,7 +286,7 @@ PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI, PORT_FreeArena(temparena, PR_TRUE); return rv; } - if (pki->privateKey.data == NULL) { + if (pki->privateKey.data == NULL || pki->privateKey.len == 0) { /* If SEC_ASN1DecodeItems succeeds but SECKEYPrivateKeyInfo.privateKey * is a zero-length octet string, free the arena and return a failure * to avoid trying to zero the corresponding SECItem in diff --git a/xpcom/io/SnappyUncompressInputStream.cpp b/xpcom/io/SnappyUncompressInputStream.cpp index 2cb3df5af5..05ae81db8b 100644 --- a/xpcom/io/SnappyUncompressInputStream.cpp +++ b/xpcom/io/SnappyUncompressInputStream.cpp @@ -22,7 +22,7 @@ static size_t CompressedBufferLength() static size_t kCompressedBufferLength = detail::SnappyFrameUtils::MaxCompressedBufferLength(snappy::kBlockSize); - MOZ_ASSERT(kCompressedBufferLength > 0); + MOZ_ASSERT(kCompressedBufferLength > detail::SnappyFrameUtils::kHeaderLength); return kCompressedBufferLength; } @@ -269,6 +269,9 @@ SnappyUncompressInputStream::ParseNextChunk(uint32_t* aBytesReadOut) // Read at least that much from the base stream. uint32_t readLength = mNextChunkDataLength; MOZ_ASSERT(readLength <= CompressedBufferLength()); + if (readLength > CompressedBufferLength() - kHeaderLength) { + return NS_ERROR_CORRUPTED_CONTENT; + } // However, if there is enough data in the base stream, also read the next // chunk header. This helps optimize the stream by avoiding many small reads.