void AudioBuffer::CopyToChannel(JSContext* aJSContext, const Float32Array& aSource, uint32_t aChannelNumber, uint32_t aStartInChannel, ErrorResult& aRv) { aSource.ComputeLengthAndData(); uint32_t length = aSource.Length(); CheckedInt<uint32_t> end = aStartInChannel; end += length; if (aChannelNumber >= NumberOfChannels() || !end.isValid() || end.value() > mLength) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } if (!mSharedChannels && JS_GetTypedArrayLength(mJSChannels[aChannelNumber]) != mLength) { // The array was probably neutered aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } if (!RestoreJSChannelData(aJSContext)) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } PodMove(JS_GetFloat32ArrayData(mJSChannels[aChannelNumber]) + aStartInChannel, aSource.Data(), length); }
size_t LZ4::compress(const char* aSource, size_t aInputSize, char* aDest) { CheckedInt<int> inputSizeChecked = aInputSize; MOZ_ASSERT(inputSizeChecked.isValid()); return LZ4_compress(aSource, aDest, inputSizeChecked.value()); }
bool WebGLBuffer::associateBufferSubDataImpl(GC3Dintptr offset, ArrayBuffer* array, GC3Dintptr arrayByteOffset, GC3Dsizeiptr byteLength) { if (!array || offset < 0 || arrayByteOffset < 0 || byteLength < 0) return false; if (byteLength) { CheckedInt<GC3Dintptr> checkedBufferOffset(offset); CheckedInt<GC3Dintptr> checkedArrayOffset(arrayByteOffset); CheckedInt<GC3Dsizeiptr> checkedLength(byteLength); CheckedInt<GC3Dintptr> checkedArrayMax = checkedArrayOffset + checkedLength; CheckedInt<GC3Dintptr> checkedBufferMax = checkedBufferOffset + checkedLength; if (!checkedArrayMax.valid() || checkedArrayMax.value() > static_cast<int32_t>(array->byteLength()) || !checkedBufferMax.valid() || checkedBufferMax.value() > m_byteLength) return false; } switch (m_target) { case GraphicsContext3D::ELEMENT_ARRAY_BUFFER: clearCachedMaxIndices(); if (byteLength) { if (!m_elementArrayBuffer) return false; memcpy(static_cast<unsigned char*>(m_elementArrayBuffer->data()) + offset, static_cast<unsigned char*>(array->data()) + arrayByteOffset, byteLength); } return true; case GraphicsContext3D::ARRAY_BUFFER: return true; default: return false; } }
nsresult mozHunspell::ConvertCharset(const nsAString& aStr, std::string& aDst) { if (NS_WARN_IF(!mEncoder)) { return NS_ERROR_NOT_INITIALIZED; } auto src = MakeSpan(aStr.BeginReading(), aStr.Length()); CheckedInt<size_t> needed = mEncoder->MaxBufferLengthFromUTF16WithoutReplacement(src.Length()); if (!needed.isValid()) { return NS_ERROR_OUT_OF_MEMORY; } aDst.resize(needed.value()); char* dstPtr = &aDst[0]; auto dst = MakeSpan(reinterpret_cast<uint8_t*>(dstPtr), needed.value()); uint32_t result; size_t read; size_t written; Tie(result, read, written) = mEncoder->EncodeFromUTF16WithoutReplacement(src, dst, true); Unused << read; MOZ_ASSERT(result != kOutputFull); if (result != kInputEmpty) { return NS_ERROR_UENC_NOMAPPING; } aDst.resize(written); mEncoder->Encoding()->NewEncoderInto(*mEncoder); return NS_OK; }
void AllocateAudioBlock(uint32_t aChannelCount, AudioChunk* aChunk) { if (aChunk->mBuffer && !aChunk->mBuffer->IsShared() && aChunk->ChannelCount() == aChannelCount) { MOZ_ASSERT(aChunk->mBufferFormat == AUDIO_FORMAT_FLOAT32); MOZ_ASSERT(aChunk->mDuration == WEBAUDIO_BLOCK_SIZE); // No need to allocate again. aChunk->mVolume = 1.0f; return; } CheckedInt<size_t> size = WEBAUDIO_BLOCK_SIZE; size *= aChannelCount; size *= sizeof(float); if (!size.isValid()) { MOZ_CRASH(); } // XXX for SIMD purposes we should do something here to make sure the // channel buffers are 16-byte aligned. nsRefPtr<SharedBuffer> buffer = SharedBuffer::Create(size.value()); aChunk->mDuration = WEBAUDIO_BLOCK_SIZE; aChunk->mChannelData.SetLength(aChannelCount); float* data = static_cast<float*>(buffer->Data()); for (uint32_t i = 0; i < aChannelCount; ++i) { aChunk->mChannelData[i] = data + i*WEBAUDIO_BLOCK_SIZE; } aChunk->mBuffer = buffer.forget(); aChunk->mVolume = 1.0f; aChunk->mBufferFormat = AUDIO_FORMAT_FLOAT32; }
bool LZ4::decompress(const char* aSource, char* aDest, size_t aOutputSize) { CheckedInt<int> outputSizeChecked = aOutputSize; MOZ_ASSERT(outputSizeChecked.isValid()); int ret = LZ4_decompress_fast(aSource, aDest, outputSizeChecked.value()); return ret >= 0; }
PassRefPtr<DataView> DataView::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength) { RELEASE_ASSERT(byteOffset <= buffer->byteLength()); CheckedInt<uint32_t> checkedOffset(byteOffset); CheckedInt<uint32_t> checkedLength(byteLength); CheckedInt<uint32_t> checkedMax = checkedOffset + checkedLength; RELEASE_ASSERT(checkedMax.isValid()); RELEASE_ASSERT(checkedMax.value() <= buffer->byteLength()); return adoptRef(new DataView(buffer, byteOffset, byteLength)); }
uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride, const gfx::IntSize& aCbCrSize, int32_t aCbCrStride, uint32_t aYOffset, uint32_t aCbOffset, uint32_t aCrOffset) { MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0); if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0 || !gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height)) || !gfx::Factory::AllowedSurfaceSize(IntSize(aCbCrStride, aCbCrSize.height))) { return 0; } uint32_t yLength = GetAlignedStride<4>(aYStride, aYSize.height); uint32_t cbCrLength = GetAlignedStride<4>(aCbCrStride, aCbCrSize.height); if (yLength == 0 || cbCrLength == 0) { return 0; } CheckedInt<uint32_t> yEnd = aYOffset; yEnd += yLength; CheckedInt<uint32_t> cbEnd = aCbOffset; cbEnd += cbCrLength; CheckedInt<uint32_t> crEnd = aCrOffset; crEnd += cbCrLength; if (!yEnd.isValid() || !cbEnd.isValid() || !crEnd.isValid() || yEnd.value() > aCbOffset || cbEnd.value() > aCrOffset) { return 0; } return crEnd.value(); }
void ChildSHistory::Go(int32_t aOffset, ErrorResult& aRv) { CheckedInt<int32_t> index = Index(); index += aOffset; if (!index.isValid()) { aRv.Throw(NS_ERROR_FAILURE); return; } aRv = mHistory->GotoIndex(index.value()); }
PassRefPtr<DataView> DataView::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength) { if (byteOffset > buffer->byteLength()) return 0; CheckedInt<uint32_t> checkedOffset(byteOffset); CheckedInt<uint32_t> checkedLength(byteLength); CheckedInt<uint32_t> checkedMax = checkedOffset + checkedLength; if (!checkedMax.isValid() || checkedMax.value() > buffer->byteLength()) return 0; return adoptRef(new DataView(buffer, byteOffset, byteLength)); }
HRESULT FramesToUsecs(int64_t aSamples, uint32_t aRate, int64_t* aOutUsecs) { MOZ_ASSERT(aOutUsecs); CheckedInt<int64_t> i = aSamples; i *= USECS_PER_S; i /= aRate; NS_ENSURE_TRUE(i.isValid(), E_FAIL); *aOutUsecs = i.value(); return S_OK; }
int32_t ComputeRGBStride(SurfaceFormat aFormat, int32_t aWidth) { CheckedInt<int32_t> size = BytesPerPixel(aFormat); size *= aWidth; if (!size.isValid() || size.value() <= 0) { gfxDebug() << "ComputeStride overflow " << aWidth; return 0; } return GetAlignedStride<4>(size.value()); }
HRESULT HNsToFrames(int64_t aHNs, uint32_t aRate, int64_t* aOutFrames) { MOZ_ASSERT(aOutFrames); const int64_t HNS_PER_S = USECS_PER_S * 10; CheckedInt<int64_t> i = aHNs; i *= aRate; i /= HNS_PER_S; NS_ENSURE_TRUE(i.isValid(), E_FAIL); *aOutFrames = i.value(); return S_OK; }
void RequestContext::ScheduleUnblock() { MOZ_ASSERT(!IsNeckoChild()); MOZ_ASSERT(NS_IsMainThread()); if (!gHttpHandler) { return; } uint32_t quantum = gHttpHandler->TailBlockingDelayQuantum(mAfterDOMContentLoaded); uint32_t delayMax = gHttpHandler->TailBlockingDelayMax(); uint32_t totalMax = gHttpHandler->TailBlockingTotalMax(); if (!mBeginLoadTime.IsNull()) { // We decrease the maximum delay progressively with the time since the page load // begin. This seems like a reasonable and clear heuristic allowing us to start // loading tailed requests in a deterministic time after the load has started. uint32_t sinceBeginLoad = static_cast<uint32_t>( (TimeStamp::NowLoRes() - mBeginLoadTime).ToMilliseconds()); uint32_t tillTotal = totalMax - std::min(sinceBeginLoad, totalMax); uint32_t proportion = totalMax // values clamped between 0 and 60'000 ? (delayMax * tillTotal) / totalMax : 0; delayMax = std::min(delayMax, proportion); } CheckedInt<uint32_t> delay = quantum * mNonTailRequests; if (!mAfterDOMContentLoaded) { // Before DOMContentLoaded notification we want to make sure that tailed // requests don't start when there is a short delay during which we may // not have any active requests on the page happening. delay += quantum; } if (!delay.isValid() || delay.value() > delayMax) { delay = delayMax; } LOG(("RequestContext::ScheduleUnblock this=%p non-tails=%u tail-queue=%zu delay=%u after-DCL=%d", this, mNonTailRequests, mTailQueue.Length(), delay.value(), mAfterDOMContentLoaded)); TimeStamp now = TimeStamp::NowLoRes(); mUntailAt = now + TimeDuration::FromMilliseconds(delay.value()); if (mTimerScheduledAt.IsNull() || mUntailAt < mTimerScheduledAt) { LOG(("RequestContext %p timer would fire too late, rescheduling", this)); RescheduleUntailTimer(now); } }
Deinterlacer::Deinterlacer(const nsIntSize& aImageSize) : mImageSize(aImageSize) { CheckedInt<size_t> bufferSize = mImageSize.width; bufferSize *= mImageSize.height; bufferSize *= sizeof(uint32_t); if (!bufferSize.isValid()) { return; } mBuffer = MakeUniqueFallible<uint8_t[]>(bufferSize.value()); }
void WebGLContext::UpdateLastUseIndex() { static CheckedInt<uint64_t> sIndex = 0; sIndex++; // should never happen with 64-bit; trying to handle this would be riskier than // not handling it as the handler code would never get exercised. if (!sIndex.isValid()) { NS_RUNTIMEABORT("Can't believe it's been 2^64 transactions already!"); } mLastUseIndex = sIndex.value(); }
NS_IMETHODIMP nsConverterInputStream::Init(nsIInputStream* aStream, const char *aCharset, int32_t aBufferSize, char16_t aReplacementChar) { nsAutoCString label; if (!aCharset) { label.AssignLiteral("UTF-8"); } else { label = aCharset; } auto encoding = Encoding::ForLabelNoReplacement(label); if (!encoding) { return NS_ERROR_UCONV_NOCONV; } // Previously, the implementation auto-switched only // between the two UTF-16 variants and only when // initialized with an endianness-unspecific label. mConverter = encoding->NewDecoder(); size_t outputBufferSize; if (aBufferSize <= 0) { aBufferSize = CONVERTER_BUFFER_SIZE; outputBufferSize = CONVERTER_BUFFER_SIZE; } else { // NetUtil.jsm assumes that if buffer size equals // the input size, the whole stream will be processed // as one readString. This is not true with encoding_rs, // because encoding_rs might want to see space for a // surrogate pair, so let's compute a larger output // buffer length. CheckedInt<size_t> needed = mConverter->MaxUTF16BufferLength(aBufferSize); if (!needed.isValid()) { return NS_ERROR_OUT_OF_MEMORY; } outputBufferSize = needed.value(); } // set up our buffers. if (!mByteData.SetCapacity(aBufferSize, mozilla::fallible) || !mUnicharData.SetLength(outputBufferSize, mozilla::fallible)) { return NS_ERROR_OUT_OF_MEMORY; } mInput = aStream; mErrorsAreFatal = !aReplacementChar; return NS_OK; }
static already_AddRefed<AudioBlockBuffer> Create(uint32_t aChannelCount) { CheckedInt<size_t> size = WEBAUDIO_BLOCK_SIZE; size *= aChannelCount; size *= sizeof(float); size += sizeof(AudioBlockBuffer); if (!size.isValid()) { MOZ_CRASH(); } void* m = moz_xmalloc(size.value()); nsRefPtr<AudioBlockBuffer> p = new (m) AudioBlockBuffer(); NS_ASSERTION((reinterpret_cast<char*>(p.get() + 1) - reinterpret_cast<char*>(p.get())) % 4 == 0, "AudioBlockBuffers should be at least 4-byte aligned"); return p.forget(); }
static bool DecodeMemory(JSContext* cx, Decoder& d, ModuleGenerator& mg, MutableHandle<ArrayBufferObject*> heap) { uint32_t sectionStart; if (!d.startSection(MemoryId, §ionStart)) return Fail(cx, d, "failed to start section"); if (sectionStart == Decoder::NotStarted) return true; uint32_t initialSizePages; if (!d.readVarU32(&initialSizePages)) return Fail(cx, d, "expected initial memory size"); CheckedInt<int32_t> initialSize = initialSizePages; initialSize *= PageSize; if (!initialSize.isValid()) return Fail(cx, d, "initial memory size too big"); uint32_t maxSizePages; if (!d.readVarU32(&maxSizePages)) return Fail(cx, d, "expected initial memory size"); CheckedInt<int32_t> maxSize = maxSizePages; maxSize *= PageSize; if (!maxSize.isValid()) return Fail(cx, d, "initial memory size too big"); uint8_t exported; if (!d.readFixedU8(&exported)) return Fail(cx, d, "expected exported byte"); if (exported) { UniqueChars fieldName = DuplicateString("memory"); if (!fieldName || !mg.addMemoryExport(Move(fieldName))) return false; } if (!d.finishSection(sectionStart)) return Fail(cx, d, "memory section byte size mismatch"); bool signalsForOOB = CompileArgs(cx).useSignalHandlersForOOB; heap.set(ArrayBufferObject::createForWasm(cx, initialSize.value(), signalsForOOB)); if (!heap) return false; mg.initHeapUsage(HeapUsage::Unshared); return true; }
static sk_sp<SkData> MakeSkData(unsigned char* aData, const IntSize& aSize, int32_t aStride) { CheckedInt<size_t> size = aStride; size *= aSize.height; if (size.isValid()) { void* mem = sk_malloc_flags(size.value(), 0); if (mem) { if (aData) { memcpy(mem, aData, size.value()); } return SkData::MakeFromMalloc(mem, size.value()); } } return nullptr; }
static bool AstDecodeMemorySection(AstDecodeContext& c) { uint32_t sectionStart, sectionSize; if (!c.d.startSection(MemorySectionId, §ionStart, §ionSize)) return AstDecodeFail(c, "failed to start section"); if (sectionStart == Decoder::NotStarted) return true; uint32_t initialSizePages; if (!c.d.readVarU32(&initialSizePages)) return AstDecodeFail(c, "expected initial memory size"); CheckedInt<uint32_t> initialSize = initialSizePages; initialSize *= PageSize; if (!initialSize.isValid()) return AstDecodeFail(c, "initial memory size too big"); uint32_t maxSizePages; if (!c.d.readVarU32(&maxSizePages)) return AstDecodeFail(c, "expected initial memory size"); CheckedInt<uint32_t> maxSize = maxSizePages; maxSize *= PageSize; if (!maxSize.isValid()) return AstDecodeFail(c, "maximum memory size too big"); uint8_t exported; if (!c.d.readFixedU8(&exported)) return AstDecodeFail(c, "expected exported byte"); c.initialSizePages.emplace(initialSizePages); if (initialSizePages != maxSizePages) { c.maxSizePages.emplace(maxSizePages); } if (exported) { AstExport* export_ = new(c.lifo) AstExport(AstName(MOZ_UTF16("memory"), 6)); if (!export_ || !c.module().append(export_)) return false; } if (!c.d.finishSection(sectionStart, sectionSize)) return AstDecodeFail(c, "memory section byte size mismatch"); return true; }
nsresult FileReader::DoReadData(uint64_t aCount) { MOZ_ASSERT(mAsyncStream); if (mDataFormat == FILE_AS_BINARY) { //Continuously update our binary string as data comes in uint32_t oldLen = mResult.Length(); NS_ASSERTION(mResult.Length() == mDataLen, "unexpected mResult length"); if (uint64_t(oldLen) + aCount > UINT32_MAX) return NS_ERROR_OUT_OF_MEMORY; char16_t *buf = nullptr; mResult.GetMutableData(&buf, oldLen + aCount, fallible); NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY); uint32_t bytesRead = 0; mAsyncStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount, &bytesRead); NS_ASSERTION(bytesRead == aCount, "failed to read data"); } else { CheckedInt<uint64_t> size = mDataLen; size += aCount; //Update memory buffer to reflect the contents of the file if (!size.isValid() || // PR_Realloc doesn't support over 4GB memory size even if 64-bit OS size.value() > UINT32_MAX || size.value() > mTotal) { return NS_ERROR_OUT_OF_MEMORY; } if (mDataFormat != FILE_AS_ARRAYBUFFER) { mFileData = (char *) realloc(mFileData, mDataLen + aCount); NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY); } uint32_t bytesRead = 0; mAsyncStream->Read(mFileData + mDataLen, aCount, &bytesRead); NS_ASSERTION(bytesRead == aCount, "failed to read data"); } mDataLen += aCount; return NS_OK; }
void AudioBuffer::CopyFromChannel(const Float32Array& aDestination, uint32_t aChannelNumber, uint32_t aStartInChannel, ErrorResult& aRv) { aDestination.ComputeLengthAndData(); uint32_t length = aDestination.Length(); CheckedInt<uint32_t> end = aStartInChannel; end += length; if (aChannelNumber >= NumberOfChannels() || !end.isValid() || end.value() > Length()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } JS::AutoCheckCannotGC nogc; JSObject* channelArray = mJSChannels[aChannelNumber]; if (channelArray) { if (JS_GetTypedArrayLength(channelArray) != Length()) { // The array's buffer was detached. aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } bool isShared = false; const float* sourceData = JS_GetFloat32ArrayData(channelArray, &isShared, nogc); // The sourceData arrays should all have originated in // RestoreJSChannelData, where they are created unshared. MOZ_ASSERT(!isShared); PodMove(aDestination.Data(), sourceData + aStartInChannel, length); return; } if (!mSharedChannels.IsNull()) { CopyChannelDataToFloat(mSharedChannels, aChannelNumber, aStartInChannel, aDestination.Data(), length); return; } PodZero(aDestination.Data(), length); }
/* static */ bool gfxASurface::CheckSurfaceSize(const gfxIntSize& sz, int32_t limit) { if (sz.width < 0 || sz.height < 0) { NS_WARNING("Surface width or height < 0!"); return false; } // reject images with sides bigger than limit if (limit && (sz.width > limit || sz.height > limit)) { NS_WARNING("Surface size too large (exceeds caller's limit)!"); return false; } #if defined(XP_MACOSX) // CoreGraphics is limited to images < 32K in *height*, // so clamp all surfaces on the Mac to that height if (sz.height > SHRT_MAX) { NS_WARNING("Surface size too large (exceeds CoreGraphics limit)!"); return false; } #endif // make sure the surface area doesn't overflow a int32_t CheckedInt<int32_t> tmp = sz.width; tmp *= sz.height; if (!tmp.isValid()) { NS_WARNING("Surface size too large (would overflow)!"); return false; } // assuming 4-byte stride, make sure the allocation size // doesn't overflow a int32_t either tmp *= 4; if (!tmp.isValid()) { NS_WARNING("Allocation too large (would overflow)!"); return false; } return true; }
bool WebGLBuffer::associateBufferDataImpl(ArrayBuffer* array, GC3Dintptr byteOffset, GC3Dsizeiptr byteLength) { if (byteLength < 0 || byteOffset < 0) return false; if (array && byteLength) { CheckedInt<GC3Dintptr> checkedOffset(byteOffset); CheckedInt<GC3Dsizeiptr> checkedLength(byteLength); CheckedInt<GC3Dintptr> checkedMax = checkedOffset + checkedLength; if (!checkedMax.valid() || checkedMax.value() > static_cast<int32_t>(array->byteLength())) return false; } switch (m_target) { case GraphicsContext3D::ELEMENT_ARRAY_BUFFER: m_byteLength = byteLength; clearCachedMaxIndices(); if (byteLength) { m_elementArrayBuffer = ArrayBuffer::create(byteLength, 1); if (!m_elementArrayBuffer) { m_byteLength = 0; return false; } if (array) { // We must always clone the incoming data because client-side // modifications without calling bufferData or bufferSubData // must never be able to change the validation results. memcpy(static_cast<unsigned char*>(m_elementArrayBuffer->data()), static_cast<unsigned char*>(array->data()) + byteOffset, byteLength); } } else m_elementArrayBuffer = 0; return true; case GraphicsContext3D::ARRAY_BUFFER: m_byteLength = byteLength; return true; default: return false; } }
uint32_t ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize, SurfaceFormat aFormat) { MOZ_ASSERT(aSize.height >= 0 && aSize.width >= 0); if (aSize.height <= 0 || aSize.width <= 0) { gfxDebug() << "Non-positive image buffer size request " << aSize.width << "x" << aSize.height; return 0; } CheckedInt<int32_t> bufsize = ComputeStride(aFormat, aSize.width); bufsize *= aSize.height; if (!bufsize.isValid() || bufsize.value() <= 0) { gfxDebug() << "Buffer size overflow " << aSize.width << "x" << aSize.height; return 0; } return SurfaceBufferInfo::GetOffset() + GetAlignedStride<16>(bufsize.value()); }
already_AddRefed<mozilla::MediaByteBuffer> MoofParser::Metadata() { MediaByteRange moov; ScanForMetadata(moov); CheckedInt<MediaByteBuffer::size_type> moovLength = moov.Length(); if (!moovLength.isValid() || !moovLength.value()) { // No moov, or cannot be used as array size. return nullptr; } RefPtr<MediaByteBuffer> metadata = new MediaByteBuffer(); if (!metadata->SetLength(moovLength.value(), fallible)) { LOG(Moof, "OOM"); return nullptr; } RefPtr<BlockingStream> stream = new BlockingStream(mSource); size_t read; bool rv = stream->ReadAt(moov.mStart, metadata->Elements(), moovLength.value(), &read); if (!rv || read != moovLength.value()) { return nullptr; } return metadata.forget(); }
// While timevaladd is widely available to work with timevals, the newer // timespec structure is largely lacking such conveniences. Thankfully, the // utilities available in MFBT make implementing our own quite easy. static void moz_timespecadd(struct timespec* lhs, struct timespec* rhs, struct timespec* result) { // Add nanoseconds. This may wrap, but not above 2 billion. MOZ_RELEASE_ASSERT(lhs->tv_nsec < NanoSecPerSec); MOZ_RELEASE_ASSERT(rhs->tv_nsec < NanoSecPerSec); result->tv_nsec = lhs->tv_nsec + rhs->tv_nsec; // Add seconds, checking for overflow in the platform specific time_t type. CheckedInt<time_t> sec = CheckedInt<time_t>(lhs->tv_sec) + rhs->tv_sec; // If nanoseconds overflowed, carry the result over into seconds. if (result->tv_nsec >= NanoSecPerSec) { MOZ_RELEASE_ASSERT(result->tv_nsec < 2 * NanoSecPerSec); result->tv_nsec -= NanoSecPerSec; sec += 1; } // Extracting the value asserts that there was no overflow. MOZ_RELEASE_ASSERT(sec.isValid()); result->tv_sec = sec.value(); }
bool WebGLContext::ValidateDataOffsetSize(WebGLintptr offset, WebGLsizeiptr size, WebGLsizeiptr bufferSize, const char* info) { if (offset < 0) { ErrorInvalidValue("%s: offset must be positive", info); return false; } if (size < 0) { ErrorInvalidValue("%s: size must be positive", info); return false; } // *** Careful *** WebGLsizeiptr is always 64-bits but GLsizeiptr // is like intptr_t. On some platforms it is 32-bits. CheckedInt<GLsizeiptr> neededBytes = CheckedInt<GLsizeiptr>(offset) + size; if (!neededBytes.isValid() || neededBytes.value() > bufferSize) { ErrorInvalidValue("%s: invalid range", info); return false; } return true; }
void AudioBuffer::CopyToChannel(JSContext* aJSContext, const Float32Array& aSource, uint32_t aChannelNumber, uint32_t aStartInChannel, ErrorResult& aRv) { aSource.ComputeLengthAndData(); uint32_t length = aSource.Length(); CheckedInt<uint32_t> end = aStartInChannel; end += length; if (aChannelNumber >= NumberOfChannels() || !end.isValid() || end.value() > mLength) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } if (!RestoreJSChannelData(aJSContext)) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } JS::AutoCheckCannotGC nogc; JSObject* channelArray = mJSChannels[aChannelNumber]; if (JS_GetTypedArrayLength(channelArray) != mLength) { // The array's buffer was detached. aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } bool isShared = false; float* channelData = JS_GetFloat32ArrayData(channelArray, &isShared, nogc); // The channelData arrays should all have originated in // RestoreJSChannelData, where they are created unshared. MOZ_ASSERT(!isShared); PodMove(channelData + aStartInChannel, aSource.Data(), length); }