void nsSocketTransportService::ProbeMaxCount() { NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); if (mProbedMaxCount) return; mProbedMaxCount = true; // Allocate and test a PR_Poll up to the gMaxCount number of unconnected // sockets. See bug 692260 - windows should be able to handle 1000 sockets // in select() without a problem, but LSPs have been known to balk at lower // numbers. (64 in the bug). // Allocate struct PRPollDesc pfd[SOCKET_LIMIT_TARGET]; uint32_t numAllocated = 0; for (uint32_t index = 0 ; index < gMaxCount; ++index) { pfd[index].in_flags = PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT; pfd[index].out_flags = 0; pfd[index].fd = PR_OpenTCPSocket(PR_AF_INET); if (!pfd[index].fd) { SOCKET_LOG(("Socket Limit Test index %d failed\n", index)); if (index < SOCKET_LIMIT_MIN) gMaxCount = SOCKET_LIMIT_MIN; else gMaxCount = index; break; } ++numAllocated; } // Test PR_STATIC_ASSERT(SOCKET_LIMIT_MIN >= 32U); while (gMaxCount <= numAllocated) { int32_t rv = PR_Poll(pfd, gMaxCount, PR_MillisecondsToInterval(0)); SOCKET_LOG(("Socket Limit Test poll() size=%d rv=%d\n", gMaxCount, rv)); if (rv >= 0) break; SOCKET_LOG(("Socket Limit Test poll confirmationSize=%d rv=%d error=%d\n", gMaxCount, rv, PR_GetError())); gMaxCount -= 32; if (gMaxCount <= SOCKET_LIMIT_MIN) { gMaxCount = SOCKET_LIMIT_MIN; break; } } // Free for (uint32_t index = 0 ; index < numAllocated; ++index) if (pfd[index].fd) PR_Close(pfd[index].fd); Telemetry::Accumulate(Telemetry::NETWORK_PROBE_MAXCOUNT, gMaxCount); SOCKET_LOG(("Socket Limit Test max was confirmed at %d\n", gMaxCount)); }
/** * this function is called to prepare mData for writing. the given capacity * indicates the required minimum storage size for mData, in sizeof(char_type) * increments. this function returns true if the operation succeeds. it also * returns the old data and old flags members if mData is newly allocated. * the old data must be released by the caller. */ bool nsTSubstring_CharT::MutatePrep( size_type capacity, char_type** oldData, uint32_t* oldFlags ) { // initialize to no old data *oldData = nullptr; *oldFlags = 0; size_type curCapacity = Capacity(); // If |capacity > kMaxCapacity|, then our doubling algorithm may not be // able to allocate it. Just bail out in cases like that. We don't want // to be allocating 2GB+ strings anyway. PR_STATIC_ASSERT((sizeof(nsStringBuffer) & 0x1) == 0); const size_type kMaxCapacity = (size_type(-1)/2 - sizeof(nsStringBuffer)) / sizeof(char_type) - 2; if (capacity > kMaxCapacity) { // Also assert for |capacity| equal to |size_type(-1)|, since we used to // use that value to flag immutability. NS_ASSERTION(capacity != size_type(-1), "Bogus capacity"); return false; } // |curCapacity == 0| means that the buffer is immutable or 0-sized, so we // need to allocate a new buffer. We cannot use the existing buffer even // though it might be large enough. if (curCapacity != 0) { if (capacity <= curCapacity) { mFlags &= ~F_VOIDED; // mutation clears voided flag return true; } // Use doubling algorithm when forced to increase available capacity. size_type temp = curCapacity; while (temp < capacity) temp <<= 1; NS_ASSERTION(XPCOM_MIN(temp, kMaxCapacity) >= capacity, "should have hit the early return at the top"); capacity = XPCOM_MIN(temp, kMaxCapacity); } // // several cases: // // (1) we have a shared buffer (mFlags & F_SHARED) // (2) we have an owned buffer (mFlags & F_OWNED) // (3) we have a fixed buffer (mFlags & F_FIXED) // (4) we have a readonly buffer // // requiring that we in some cases preserve the data before creating // a new buffer complicates things just a bit ;-) // size_type storageSize = (capacity + 1) * sizeof(char_type); // case #1 if (mFlags & F_SHARED) { nsStringBuffer* hdr = nsStringBuffer::FromData(mData); if (!hdr->IsReadonly()) { nsStringBuffer *newHdr = nsStringBuffer::Realloc(hdr, storageSize); if (!newHdr) return false; // out-of-memory (original header left intact) hdr = newHdr; mData = (char_type*) hdr->Data(); mFlags &= ~F_VOIDED; // mutation clears voided flag return true; } } char_type* newData; uint32_t newDataFlags; // if we have a fixed buffer of sufficient size, then use it. this helps // avoid heap allocations. if ((mFlags & F_CLASS_FIXED) && (capacity < AsFixedString(this)->mFixedCapacity)) { newData = AsFixedString(this)->mFixedBuf; newDataFlags = F_TERMINATED | F_FIXED; } else { // if we reach here then, we must allocate a new buffer. we cannot // make use of our F_OWNED or F_FIXED buffers because they are not // large enough. nsStringBuffer* newHdr = nsStringBuffer::Alloc(storageSize).get(); if (!newHdr) return false; // we are still in a consistent state newData = (char_type*) newHdr->Data(); newDataFlags = F_TERMINATED | F_SHARED; } // save old data and flags *oldData = mData; *oldFlags = mFlags; mData = newData; SetDataFlags(newDataFlags); // mLength does not change // though we are not necessarily terminated at the moment, now is probably // still the best time to set F_TERMINATED. return true; }
nsresult nsSVGTransformSMILAttr::AppendSVGTransformToSMILValue( nsIDOMSVGTransform* aTransform, nsSMILValue& aValue) { NS_ASSERTION(aValue.mType == &nsSVGTransformSMILType::sSingleton, "Unexpected type for SMIL value"); PRUint16 svgTransformType = nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX; aTransform->GetType(&svgTransformType); nsCOMPtr<nsIDOMSVGMatrix> matrix; nsresult rv = aTransform->GetMatrix(getter_AddRefs(matrix)); if (NS_FAILED(rv) || !matrix) return NS_ERROR_FAILURE; // nsSVGSMILTransform constructor should be expecting array with 3 params PR_STATIC_ASSERT(nsSVGSMILTransform::NUM_SIMPLE_PARAMS == 3); float params[3] = { 0.f }; nsSVGSMILTransform::TransformType transformType; switch (svgTransformType) { case nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE: { matrix->GetE(¶ms[0]); matrix->GetF(¶ms[1]); transformType = nsSVGSMILTransform::TRANSFORM_TRANSLATE; } break; case nsIDOMSVGTransform::SVG_TRANSFORM_SCALE: { matrix->GetA(¶ms[0]); matrix->GetD(¶ms[1]); transformType = nsSVGSMILTransform::TRANSFORM_SCALE; } break; case nsIDOMSVGTransform::SVG_TRANSFORM_ROTATE: { /* * Unfortunately the SVG 1.1 DOM API for transforms doesn't allow us to * query the center of rotation so we do some dirty casting to make up * for it. */ nsSVGTransform* svgTransform = static_cast<nsSVGTransform*>(aTransform); svgTransform->GetAngle(¶ms[0]); svgTransform->GetRotationOrigin(params[1], params[2]); transformType = nsSVGSMILTransform::TRANSFORM_ROTATE; } break; case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX: { aTransform->GetAngle(¶ms[0]); transformType = nsSVGSMILTransform::TRANSFORM_SKEWX; } break; case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY: { aTransform->GetAngle(¶ms[0]); transformType = nsSVGSMILTransform::TRANSFORM_SKEWY; } break; case nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX: { // nsSVGSMILTransform constructor for TRANSFORM_MATRIX type should be // expecting array with 6 params PR_STATIC_ASSERT(nsSVGSMILTransform::NUM_STORED_PARAMS == 6); float mx[6]; matrix->GetA(&mx[0]); matrix->GetB(&mx[1]); matrix->GetC(&mx[2]); matrix->GetD(&mx[3]); matrix->GetE(&mx[4]); matrix->GetF(&mx[5]); return nsSVGTransformSMILType::AppendTransform(nsSVGSMILTransform(mx), aValue); } case nsIDOMSVGTransform::SVG_TRANSFORM_UNKNOWN: // If it's 'unknown', it's probably not initialised, so just skip it. return NS_OK; default: NS_WARNING("Trying to convert unrecognised SVG transform type"); return NS_ERROR_FAILURE; } NS_ABORT_IF_FALSE(transformType != nsSVGSMILTransform::TRANSFORM_MATRIX, "generalized matrix case should have returned above"); return nsSVGTransformSMILType:: AppendTransform(nsSVGSMILTransform(transformType, params), aValue); }
bool WaveReader::LoadFormatChunk() { uint32_t fmtSize, rate, channels, frameSize, sampleFormat; char waveFormat[WAVE_FORMAT_CHUNK_SIZE]; const char* p = waveFormat; // RIFF chunks are always word (two byte) aligned. NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0, "LoadFormatChunk called with unaligned resource"); // The "format" chunk may not directly follow the "riff" chunk, so skip // over any intermediate chunks. if (!ScanForwardUntil(FRMT_CHUNK_MAGIC, &fmtSize)) { return false; } if (!ReadAll(waveFormat, sizeof(waveFormat))) { return false; } PR_STATIC_ASSERT(sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + 4 + sizeof(uint16_t) + sizeof(uint16_t) <= sizeof(waveFormat)); if (ReadUint16LE(&p) != WAVE_FORMAT_ENCODING_PCM) { NS_WARNING("WAVE is not uncompressed PCM, compressed encodings are not supported"); return false; } channels = ReadUint16LE(&p); rate = ReadUint32LE(&p); // Skip over average bytes per second field. p += 4; frameSize = ReadUint16LE(&p); sampleFormat = ReadUint16LE(&p); // PCM encoded WAVEs are not expected to have an extended "format" chunk, // but I have found WAVEs that have a extended "format" chunk with an // extension size of 0 bytes. Be polite and handle this rather than // considering the file invalid. This code skips any extension of the // "format" chunk. if (fmtSize > WAVE_FORMAT_CHUNK_SIZE) { char extLength[2]; const char* p = extLength; if (!ReadAll(extLength, sizeof(extLength))) { return false; } PR_STATIC_ASSERT(sizeof(uint16_t) <= sizeof(extLength)); uint16_t extra = ReadUint16LE(&p); if (fmtSize - (WAVE_FORMAT_CHUNK_SIZE + 2) != extra) { NS_WARNING("Invalid extended format chunk size"); return false; } extra += extra % 2; if (extra > 0) { PR_STATIC_ASSERT(UINT16_MAX + (UINT16_MAX % 2) < UINT_MAX / sizeof(char)); nsAutoArrayPtr<char> chunkExtension(new char[extra]); if (!ReadAll(chunkExtension.get(), extra)) { return false; } } } // RIFF chunks are always word (two byte) aligned. NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0, "LoadFormatChunk left resource unaligned"); // Make sure metadata is fairly sane. The rate check is fairly arbitrary, // but the channels check is intentionally limited to mono or stereo // because that's what the audio backend currently supports. unsigned int actualFrameSize = sampleFormat == 8 ? 1 : 2 * channels; if (rate < 100 || rate > 96000 || channels < 1 || channels > MAX_CHANNELS || (frameSize != 1 && frameSize != 2 && frameSize != 4) || (sampleFormat != 8 && sampleFormat != 16) || frameSize != actualFrameSize) { NS_WARNING("Invalid WAVE metadata"); return false; } ReentrantMonitorAutoEnter monitor(mDecoder->GetReentrantMonitor()); mSampleRate = rate; mChannels = channels; mFrameSize = frameSize; if (sampleFormat == 8) { mSampleFormat = FORMAT_U8; } else { mSampleFormat = FORMAT_S16; } return true; }
/** * Translate a "rows" or "cols" spec into an array of nsFramesetSpecs */ nsresult HTMLFrameSetElement::ParseRowCol(const nsAString & aValue, int32_t& aNumSpecs, nsFramesetSpec** aSpecs) { if (aValue.IsEmpty()) { aNumSpecs = 0; *aSpecs = nullptr; return NS_OK; } static const PRUnichar sAster('*'); static const PRUnichar sPercent('%'); static const PRUnichar sComma(','); nsAutoString spec(aValue); // remove whitespace (Bug 33699) and quotation marks (bug 224598) // also remove leading/trailing commas (bug 31482) spec.StripChars(" \n\r\t\"\'"); spec.Trim(","); // Count the commas. Don't count more than X commas (bug 576447). PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT * sizeof(nsFramesetSpec) < (1 << 30)); int32_t commaX = spec.FindChar(sComma); int32_t count = 1; while (commaX != kNotFound && count < NS_MAX_FRAMESET_SPEC_COUNT) { count++; commaX = spec.FindChar(sComma, commaX + 1); } nsFramesetSpec* specs = new nsFramesetSpec[count]; if (!specs) { *aSpecs = nullptr; aNumSpecs = 0; return NS_ERROR_OUT_OF_MEMORY; } // Pre-grab the compat mode; we may need it later in the loop. bool isInQuirks = InNavQuirksMode(OwnerDoc()); // Parse each comma separated token int32_t start = 0; int32_t specLen = spec.Length(); for (int32_t i = 0; i < count; i++) { // Find our comma commaX = spec.FindChar(sComma, start); NS_ASSERTION(i == count - 1 || commaX != kNotFound, "Failed to find comma, somehow"); int32_t end = (commaX == kNotFound) ? specLen : commaX; // Note: If end == start then it means that the token has no // data in it other than a terminating comma (or the end of the spec). // So default to a fixed width of 0. specs[i].mUnit = eFramesetUnit_Fixed; specs[i].mValue = 0; if (end > start) { int32_t numberEnd = end; PRUnichar ch = spec.CharAt(numberEnd - 1); if (sAster == ch) { specs[i].mUnit = eFramesetUnit_Relative; numberEnd--; } else if (sPercent == ch) { specs[i].mUnit = eFramesetUnit_Percent; numberEnd--; // check for "*%" if (numberEnd > start) { ch = spec.CharAt(numberEnd - 1); if (sAster == ch) { specs[i].mUnit = eFramesetUnit_Relative; numberEnd--; } } } // Translate value to an integer nsAutoString token; spec.Mid(token, start, numberEnd - start); // Treat * as 1* if ((eFramesetUnit_Relative == specs[i].mUnit) && (0 == token.Length())) { specs[i].mValue = 1; } else { // Otherwise just convert to integer. nsresult err; specs[i].mValue = token.ToInteger(&err); if (NS_FAILED(err)) { specs[i].mValue = 0; } } // Treat 0* as 1* in quirks mode (bug 40383) if (isInQuirks) { if ((eFramesetUnit_Relative == specs[i].mUnit) && (0 == specs[i].mValue)) { specs[i].mValue = 1; } } // Catch zero and negative frame sizes for Nav compatibility // Nav resized absolute and relative frames to "1" and // percent frames to an even percentage of the width // //if (isInQuirks && (specs[i].mValue <= 0)) { // if (eFramesetUnit_Percent == specs[i].mUnit) { // specs[i].mValue = 100 / count; // } else { // specs[i].mValue = 1; // } //} else { // In standards mode, just set negative sizes to zero if (specs[i].mValue < 0) { specs[i].mValue = 0; } start = end + 1; } } aNumSpecs = count; // Transfer ownership to caller here *aSpecs = specs; return NS_OK; }
static SECStatus rc4_wordconv(RC4Context *cx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, const unsigned char *input, unsigned int inputLen) { PR_STATIC_ASSERT(sizeof(PRUword) == sizeof(ptrdiff_t)); unsigned int inOffset = (PRUword)input % WORDSIZE; unsigned int outOffset = (PRUword)output % WORDSIZE; register WORD streamWord; register const WORD *pInWord; register WORD *pOutWord; register WORD inWord, nextInWord; PRUint8 t; register Stype tmpSi, tmpSj; register PRUint8 tmpi = cx->i; register PRUint8 tmpj = cx->j; unsigned int bufShift, invBufShift; unsigned int i; const unsigned char *finalIn; unsigned char *finalOut; PORT_Assert(maxOutputLen >= inputLen); if (maxOutputLen < inputLen) { PORT_SetError(SEC_ERROR_OUTPUT_LEN); return SECFailure; } if (inputLen < 2*WORDSIZE) { /* Ignore word conversion, do byte-at-a-time */ return rc4_no_opt(cx, output, outputLen, maxOutputLen, input, inputLen); } *outputLen = inputLen; pInWord = (const WORD *)(input - inOffset); pOutWord = (WORD *)(output - outOffset); if (inOffset <= outOffset) { bufShift = 8*(outOffset - inOffset); invBufShift = 8*WORDSIZE - bufShift; } else { invBufShift = 8*(inOffset - outOffset); bufShift = 8*WORDSIZE - invBufShift; } /*****************************************************************/ /* Step 1: */ /* If the first output word is partial, consume the bytes in the */ /* first partial output word by loading one or two words of */ /* input and shifting them accordingly. Otherwise, just load */ /* in the first word of input. At the end of this block, at */ /* least one partial word of input should ALWAYS be loaded. */ /*****************************************************************/ if (outOffset) { unsigned int byteCount = WORDSIZE - outOffset; for (i = 0; i < byteCount; i++) { ARCFOUR_NEXT_BYTE(); output[i] = cx->S[t] ^ input[i]; } /* Consumed byteCount bytes of input */ inputLen -= byteCount; pInWord++; /* move to next word of output */ pOutWord++; /* If buffers are relatively misaligned, shift the bytes in inWord * to be aligned to the output buffer. */ if (inOffset < outOffset) { /* The first input word (which may be partial) has more bytes * than needed. Copy the remainder to inWord. */ unsigned int shift = LEFTMOST_BYTE_SHIFT; inWord = 0; for (i = 0; i < outOffset - inOffset; i++) { inWord |= (WORD)input[byteCount + i] << shift; shift = NEXT_BYTE_SHIFT(shift); } } else if (inOffset > outOffset) { /* Consumed some bytes in the second input word. Copy the * remainder to inWord. */ inWord = *pInWord++; inWord = inWord LSH invBufShift; } else { inWord = 0; } } else { /* output is word-aligned */ if (inOffset) { /* Input is not word-aligned. The first word load of input * will not produce a full word of input bytes, so one word * must be pre-loaded. The main loop below will load in the * next input word and shift some of its bytes into inWord * in order to create a full input word. Note that the main * loop must execute at least once because the input must * be at least two words. */ unsigned int shift = LEFTMOST_BYTE_SHIFT; inWord = 0; for (i = 0; i < WORDSIZE - inOffset; i++) { inWord |= (WORD)input[i] << shift; shift = NEXT_BYTE_SHIFT(shift); } pInWord++; } else { /* Input is word-aligned. The first word load of input * will produce a full word of input bytes, so nothing * needs to be loaded here. */ inWord = 0; } } /*****************************************************************/ /* Step 2: main loop */ /* At this point the output buffer is word-aligned. Any unused */ /* bytes from above will be in inWord (shifted correctly). If */ /* the input buffer is unaligned relative to the output buffer, */ /* shifting has to be done. */ /*****************************************************************/ if (bufShift) { /* preloadedByteCount is the number of input bytes pre-loaded * in inWord. */ unsigned int preloadedByteCount = bufShift/8; for (; inputLen >= preloadedByteCount + WORDSIZE; inputLen -= WORDSIZE) { nextInWord = *pInWord++; inWord |= nextInWord RSH bufShift; nextInWord = nextInWord LSH invBufShift; ARCFOUR_NEXT_WORD(); *pOutWord++ = inWord ^ streamWord; inWord = nextInWord; } if (inputLen == 0) { /* Nothing left to do. */ cx->i = tmpi; cx->j = tmpj; return SECSuccess; } finalIn = (const unsigned char *)pInWord - preloadedByteCount; } else { for (; inputLen >= WORDSIZE; inputLen -= WORDSIZE) { inWord = *pInWord++; ARCFOUR_NEXT_WORD(); *pOutWord++ = inWord ^ streamWord; } if (inputLen == 0) { /* Nothing left to do. */ cx->i = tmpi; cx->j = tmpj; return SECSuccess; } finalIn = (const unsigned char *)pInWord; } /*****************************************************************/ /* Step 3: */ /* Do the remaining partial word of input one byte at a time. */ /*****************************************************************/ finalOut = (unsigned char *)pOutWord; for (i = 0; i < inputLen; i++) { ARCFOUR_NEXT_BYTE(); finalOut[i] = cx->S[t] ^ finalIn[i]; } cx->i = tmpi; cx->j = tmpj; return SECSuccess; }
void nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const { // eCSSProperty_UNKNOWN gets used for some recursive calls below. NS_ABORT_IF_FALSE((0 <= aProperty && aProperty <= eCSSProperty_COUNT_no_shorthands) || aProperty == eCSSProperty_UNKNOWN, "property ID out of range"); nsCSSUnit unit = GetUnit(); if (unit == eCSSUnit_Null) { return; } if (eCSSUnit_String <= unit && unit <= eCSSUnit_Attr) { if (unit == eCSSUnit_Attr) { aResult.AppendLiteral("attr("); } nsAutoString buffer; GetStringValue(buffer); if (unit == eCSSUnit_String) { nsStyleUtil::AppendEscapedCSSString(buffer, aResult); } else if (unit == eCSSUnit_Families) { // XXX We really need to do *some* escaping. aResult.Append(buffer); } else { nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult); } } else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Steps) { switch (unit) { case eCSSUnit_Counter: aResult.AppendLiteral("counter("); break; case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break; case eCSSUnit_Cubic_Bezier: aResult.AppendLiteral("cubic-bezier("); break; case eCSSUnit_Steps: aResult.AppendLiteral("steps("); break; default: break; } nsCSSValue::Array *array = GetArrayValue(); bool mark = false; for (size_t i = 0, i_end = array->Count(); i < i_end; ++i) { if (aProperty == eCSSProperty_border_image && i >= 5) { if (array->Item(i).GetUnit() == eCSSUnit_Null) { continue; } if (i == 5) { aResult.AppendLiteral(" /"); } } if (mark && array->Item(i).GetUnit() != eCSSUnit_Null) { if (unit == eCSSUnit_Array && eCSSProperty_transition_timing_function != aProperty) aResult.AppendLiteral(" "); else aResult.AppendLiteral(", "); } if (unit == eCSSUnit_Steps && i == 1) { NS_ABORT_IF_FALSE(array->Item(i).GetUnit() == eCSSUnit_Enumerated && (array->Item(i).GetIntValue() == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START || array->Item(i).GetIntValue() == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END), "unexpected value"); if (array->Item(i).GetIntValue() == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START) { aResult.AppendLiteral("start"); } else { aResult.AppendLiteral("end"); } continue; } nsCSSProperty prop = ((eCSSUnit_Counter <= unit && unit <= eCSSUnit_Counters) && i == array->Count() - 1) ? eCSSProperty_list_style_type : aProperty; if (array->Item(i).GetUnit() != eCSSUnit_Null) { array->Item(i).AppendToString(prop, aResult); mark = true; } } if (eCSSUnit_Array == unit && aProperty == eCSSProperty_transition_timing_function) { aResult.AppendLiteral(")"); } } /* Although Function is backed by an Array, we'll handle it separately * because it's a bit quirky. */ else if (eCSSUnit_Function == unit) { const nsCSSValue::Array* array = GetArrayValue(); NS_ABORT_IF_FALSE(array->Count() >= 1, "Functions must have at least one element for the name."); /* Append the function name. */ const nsCSSValue& functionName = array->Item(0); if (functionName.GetUnit() == eCSSUnit_Enumerated) { // We assume that the first argument is always of nsCSSKeyword type. const nsCSSKeyword functionId = static_cast<nsCSSKeyword>(functionName.GetIntValue()); nsStyleUtil::AppendEscapedCSSIdent( NS_ConvertASCIItoUTF16(nsCSSKeywords::GetStringValue(functionId)), aResult); } else { functionName.AppendToString(aProperty, aResult); } aResult.AppendLiteral("("); /* Now, step through the function contents, writing each of them as we go. */ for (size_t index = 1; index < array->Count(); ++index) { array->Item(index).AppendToString(aProperty, aResult); /* If we're not at the final element, append a comma. */ if (index + 1 != array->Count()) aResult.AppendLiteral(", "); } /* Finally, append the closing parenthesis. */ aResult.AppendLiteral(")"); } else if (IsCalcUnit()) { NS_ABORT_IF_FALSE(GetUnit() == eCSSUnit_Calc, "unexpected unit"); CSSValueSerializeCalcOps ops(aProperty, aResult); css::SerializeCalc(*this, ops); } else if (eCSSUnit_Integer == unit) { aResult.AppendInt(GetIntValue(), 10); } else if (eCSSUnit_Enumerated == unit) { if (eCSSProperty_text_decoration_line == aProperty) { PRInt32 intValue = GetIntValue(); if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) { AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue), aResult); } else { // Ignore the "override all" internal value. // (It doesn't have a string representation.) intValue &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL; nsStyleUtil::AppendBitmaskCSSValue( aProperty, intValue, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS, aResult); } } else if (eCSSProperty_marks == aProperty) { PRInt32 intValue = GetIntValue(); if (intValue == NS_STYLE_PAGE_MARKS_NONE) { AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue), aResult); } else { nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue, NS_STYLE_PAGE_MARKS_CROP, NS_STYLE_PAGE_MARKS_REGISTER, aResult); } } else if (eCSSProperty_unicode_bidi == aProperty) { PR_STATIC_ASSERT(NS_STYLE_UNICODE_BIDI_NORMAL == 0); PRInt32 intValue = GetIntValue(); if (NS_STYLE_UNICODE_BIDI_NORMAL == intValue) { AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue), aResult); } else { nsStyleUtil::AppendBitmaskCSSValue( aProperty, intValue, NS_STYLE_UNICODE_BIDI_EMBED, NS_STYLE_UNICODE_BIDI_PLAINTEXT, aResult); } } else { const nsAFlatCString& name = nsCSSProps::LookupPropertyValue(aProperty, GetIntValue()); AppendASCIItoUTF16(name, aResult); } } else if (eCSSUnit_EnumColor == unit) { // we can lookup the property in the ColorTable and then // get a string mapping the name nsCAutoString str; if (nsCSSProps::GetColorName(GetIntValue(), str)){ AppendASCIItoUTF16(str, aResult); } else { NS_ABORT_IF_FALSE(false, "bad color value"); } } else if (eCSSUnit_Color == unit) { nscolor color = GetColorValue(); if (color == NS_RGBA(0, 0, 0, 0)) { // Use the strictest match for 'transparent' so we do correct // round-tripping of all other rgba() values. aResult.AppendLiteral("transparent"); } else { PRUint8 a = NS_GET_A(color); if (a < 255) { aResult.AppendLiteral("rgba("); } else { aResult.AppendLiteral("rgb("); } NS_NAMED_LITERAL_STRING(comma, ", "); aResult.AppendInt(NS_GET_R(color), 10); aResult.Append(comma); aResult.AppendInt(NS_GET_G(color), 10); aResult.Append(comma); aResult.AppendInt(NS_GET_B(color), 10); if (a < 255) { aResult.Append(comma); aResult.AppendFloat(nsStyleUtil::ColorComponentToFloat(a)); } aResult.Append(PRUnichar(')')); } } else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) { aResult.Append(NS_LITERAL_STRING("url(")); nsStyleUtil::AppendEscapedCSSString( nsDependentString(GetOriginalURLValue()), aResult); aResult.Append(NS_LITERAL_STRING(")")); } else if (eCSSUnit_Element == unit) { aResult.Append(NS_LITERAL_STRING("-moz-element(#")); nsAutoString tmpStr; GetStringValue(tmpStr); nsStyleUtil::AppendEscapedCSSIdent(tmpStr, aResult); aResult.Append(NS_LITERAL_STRING(")")); } else if (eCSSUnit_Percent == unit) { aResult.AppendFloat(GetPercentValue() * 100.0f); } else if (eCSSUnit_Percent < unit) { // length unit aResult.AppendFloat(GetFloatValue()); } else if (eCSSUnit_Gradient == unit) { nsCSSValueGradient* gradient = GetGradientValue(); if (gradient->mIsRepeating) { if (gradient->mIsRadial) aResult.AppendLiteral("-moz-repeating-radial-gradient("); else aResult.AppendLiteral("-moz-repeating-linear-gradient("); } else { if (gradient->mIsRadial) aResult.AppendLiteral("-moz-radial-gradient("); else aResult.AppendLiteral("-moz-linear-gradient("); } if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None || gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None || gradient->mAngle.GetUnit() != eCSSUnit_None) { if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None) { gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position, aResult); aResult.AppendLiteral(" "); } if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None) { gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position, aResult); aResult.AppendLiteral(" "); } if (gradient->mAngle.GetUnit() != eCSSUnit_None) { gradient->mAngle.AppendToString(aProperty, aResult); } aResult.AppendLiteral(", "); } if (gradient->mIsRadial && (gradient->mRadialShape.GetUnit() != eCSSUnit_None || gradient->mRadialSize.GetUnit() != eCSSUnit_None)) { if (gradient->mRadialShape.GetUnit() != eCSSUnit_None) { NS_ABORT_IF_FALSE(gradient->mRadialShape.GetUnit() == eCSSUnit_Enumerated, "bad unit for radial gradient shape"); PRInt32 intValue = gradient->mRadialShape.GetIntValue(); NS_ABORT_IF_FALSE(intValue != NS_STYLE_GRADIENT_SHAPE_LINEAR, "radial gradient with linear shape?!"); AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue, nsCSSProps::kRadialGradientShapeKTable), aResult); aResult.AppendLiteral(" "); } if (gradient->mRadialSize.GetUnit() != eCSSUnit_None) { NS_ABORT_IF_FALSE(gradient->mRadialSize.GetUnit() == eCSSUnit_Enumerated, "bad unit for radial gradient size"); PRInt32 intValue = gradient->mRadialSize.GetIntValue(); AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue, nsCSSProps::kRadialGradientSizeKTable), aResult); } aResult.AppendLiteral(", "); } for (PRUint32 i = 0 ;;) { gradient->mStops[i].mColor.AppendToString(aProperty, aResult); if (gradient->mStops[i].mLocation.GetUnit() != eCSSUnit_None) { aResult.AppendLiteral(" "); gradient->mStops[i].mLocation.AppendToString(aProperty, aResult); } if (++i == gradient->mStops.Length()) { break; } aResult.AppendLiteral(", "); } aResult.AppendLiteral(")"); } else if (eCSSUnit_Pair == unit) { GetPairValue().AppendToString(aProperty, aResult); } else if (eCSSUnit_Triplet == unit) { GetTripletValue().AppendToString(aProperty, aResult); } else if (eCSSUnit_Rect == unit) { GetRectValue().AppendToString(aProperty, aResult); } else if (eCSSUnit_List == unit || eCSSUnit_ListDep == unit) { GetListValue()->AppendToString(aProperty, aResult); } else if (eCSSUnit_PairList == unit || eCSSUnit_PairListDep == unit) { GetPairListValue()->AppendToString(aProperty, aResult); } switch (unit) { case eCSSUnit_Null: break; case eCSSUnit_Auto: aResult.AppendLiteral("auto"); break; case eCSSUnit_Inherit: aResult.AppendLiteral("inherit"); break; case eCSSUnit_Initial: aResult.AppendLiteral("-moz-initial"); break; case eCSSUnit_None: aResult.AppendLiteral("none"); break; case eCSSUnit_Normal: aResult.AppendLiteral("normal"); break; case eCSSUnit_System_Font: aResult.AppendLiteral("-moz-use-system-font"); break; case eCSSUnit_All: aResult.AppendLiteral("all"); break; case eCSSUnit_Dummy: case eCSSUnit_DummyInherit: NS_ABORT_IF_FALSE(false, "should never serialize"); break; case eCSSUnit_String: break; case eCSSUnit_Ident: break; case eCSSUnit_Families: break; case eCSSUnit_URL: break; case eCSSUnit_Image: break; case eCSSUnit_Element: break; case eCSSUnit_Array: break; case eCSSUnit_Attr: case eCSSUnit_Cubic_Bezier: case eCSSUnit_Steps: case eCSSUnit_Counter: case eCSSUnit_Counters: aResult.Append(PRUnichar(')')); break; case eCSSUnit_Local_Font: break; case eCSSUnit_Font_Format: break; case eCSSUnit_Function: break; case eCSSUnit_Calc: break; case eCSSUnit_Calc_Plus: break; case eCSSUnit_Calc_Minus: break; case eCSSUnit_Calc_Times_L: break; case eCSSUnit_Calc_Times_R: break; case eCSSUnit_Calc_Divided: break; case eCSSUnit_Integer: break; case eCSSUnit_Enumerated: break; case eCSSUnit_EnumColor: break; case eCSSUnit_Color: break; case eCSSUnit_Percent: aResult.Append(PRUnichar('%')); break; case eCSSUnit_Number: break; case eCSSUnit_Gradient: break; case eCSSUnit_Pair: break; case eCSSUnit_Triplet: break; case eCSSUnit_Rect: break; case eCSSUnit_List: break; case eCSSUnit_ListDep: break; case eCSSUnit_PairList: break; case eCSSUnit_PairListDep: break; case eCSSUnit_Inch: aResult.AppendLiteral("in"); break; case eCSSUnit_Millimeter: aResult.AppendLiteral("mm"); break; case eCSSUnit_PhysicalMillimeter: aResult.AppendLiteral("mozmm"); break; case eCSSUnit_Centimeter: aResult.AppendLiteral("cm"); break; case eCSSUnit_Point: aResult.AppendLiteral("pt"); break; case eCSSUnit_Pica: aResult.AppendLiteral("pc"); break; case eCSSUnit_EM: aResult.AppendLiteral("em"); break; case eCSSUnit_XHeight: aResult.AppendLiteral("ex"); break; case eCSSUnit_Char: aResult.AppendLiteral("ch"); break; case eCSSUnit_RootEM: aResult.AppendLiteral("rem"); break; case eCSSUnit_Pixel: aResult.AppendLiteral("px"); break; case eCSSUnit_Degree: aResult.AppendLiteral("deg"); break; case eCSSUnit_Grad: aResult.AppendLiteral("grad"); break; case eCSSUnit_Radian: aResult.AppendLiteral("rad"); break; case eCSSUnit_Hertz: aResult.AppendLiteral("Hz"); break; case eCSSUnit_Kilohertz: aResult.AppendLiteral("kHz"); break; case eCSSUnit_Seconds: aResult.Append(PRUnichar('s')); break; case eCSSUnit_Milliseconds: aResult.AppendLiteral("ms"); break; } }
nsresult Key::EncodeJSVal(JSContext* aCx, const jsval aVal, PRUint8 aTypeOffset) { PR_STATIC_ASSERT(eMaxType * MaxArrayCollapse < 256); if (JSVAL_IS_STRING(aVal)) { nsDependentJSString str; if (!str.init(aCx, aVal)) { return NS_ERROR_OUT_OF_MEMORY; } EncodeString(str, aTypeOffset); return NS_OK; } if (JSVAL_IS_INT(aVal)) { EncodeNumber((double)JSVAL_TO_INT(aVal), eFloat + aTypeOffset); return NS_OK; } if (JSVAL_IS_DOUBLE(aVal)) { double d = JSVAL_TO_DOUBLE(aVal); if (DOUBLE_IS_NaN(d)) { return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; } EncodeNumber(d, eFloat + aTypeOffset); return NS_OK; } if (!JSVAL_IS_PRIMITIVE(aVal)) { JSObject* obj = JSVAL_TO_OBJECT(aVal); if (JS_IsArrayObject(aCx, obj)) { aTypeOffset += eMaxType; if (aTypeOffset == eMaxType * MaxArrayCollapse) { mBuffer.Append(aTypeOffset); aTypeOffset = 0; } NS_ASSERTION((aTypeOffset % eMaxType) == 0 && aTypeOffset < (eMaxType * MaxArrayCollapse), "Wrong typeoffset"); jsuint length; if (!JS_GetArrayLength(aCx, obj, &length)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } for (jsuint index = 0; index < length; index++) { jsval val; if (!JS_GetElement(aCx, obj, index, &val)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } nsresult rv = EncodeJSVal(aCx, val, aTypeOffset); NS_ENSURE_SUCCESS(rv, rv); aTypeOffset = 0; } mBuffer.Append(eTerminator + aTypeOffset); return NS_OK; } if (JS_ObjectIsDate(aCx, obj)) { EncodeNumber(js_DateGetMsecSinceEpoch(aCx, obj), eDate + aTypeOffset); return NS_OK; } } return NS_ERROR_DOM_INDEXEDDB_DATA_ERR; }
bool WaveReader::LoadAllChunks(nsAutoPtr<nsHTMLMediaElement::MetadataTags> &aTags) { // Chunks are always word (two byte) aligned. NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0, "LoadAllChunks called with unaligned resource"); bool loadFormatChunk = false; bool findDataOffset = false; for (;;) { static const unsigned int CHUNK_HEADER_SIZE = 8; char chunkHeader[CHUNK_HEADER_SIZE]; const char* p = chunkHeader; if (!ReadAll(chunkHeader, sizeof(chunkHeader))) { return false; } PR_STATIC_ASSERT(sizeof(uint32_t) * 2 <= CHUNK_HEADER_SIZE); uint32_t magic = ReadUint32BE(&p); uint32_t chunkSize = ReadUint32LE(&p); int64_t chunkStart = GetPosition(); switch (magic) { case FRMT_CHUNK_MAGIC: loadFormatChunk = LoadFormatChunk(chunkSize); if (!loadFormatChunk) { return false; } break; case LIST_CHUNK_MAGIC: if (!aTags) { LoadListChunk(chunkSize, aTags); } break; case DATA_CHUNK_MAGIC: findDataOffset = FindDataOffset(chunkSize); return loadFormatChunk && findDataOffset; default: break; } // RIFF chunks are two-byte aligned, so round up if necessary. chunkSize += chunkSize % 2; // Move forward to next chunk CheckedInt64 forward = CheckedInt64(chunkStart) + chunkSize - GetPosition(); if (!forward.isValid() || forward.value() < 0) { return false; } static const int64_t MAX_CHUNK_SIZE = 1 << 16; PR_STATIC_ASSERT(uint64_t(MAX_CHUNK_SIZE) < UINT_MAX / sizeof(char)); nsAutoArrayPtr<char> chunk(new char[MAX_CHUNK_SIZE]); while (forward.value() > 0) { int64_t size = NS_MIN(forward.value(), MAX_CHUNK_SIZE); if (!ReadAll(chunk.get(), size)) { return false; } forward -= size; } } return false; }
bool WaveReader::LoadListChunk(uint32_t aChunkSize, nsAutoPtr<nsHTMLMediaElement::MetadataTags> &aTags) { // List chunks are always word (two byte) aligned. NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0, "LoadListChunk called with unaligned resource"); static const unsigned int MAX_CHUNK_SIZE = 1 << 16; PR_STATIC_ASSERT(MAX_CHUNK_SIZE < UINT_MAX / sizeof(char)); if (aChunkSize > MAX_CHUNK_SIZE) { return false; } nsAutoArrayPtr<char> chunk(new char[aChunkSize]); if (!ReadAll(chunk.get(), aChunkSize)) { return false; } static const uint32_t INFO_LIST_MAGIC = 0x494e464f; const char *p = chunk.get(); if (ReadUint32BE(&p) != INFO_LIST_MAGIC) { return false; } const waveIdToName ID_TO_NAME[] = { { 0x49415254, NS_LITERAL_CSTRING("artist") }, // IART { 0x49434d54, NS_LITERAL_CSTRING("comments") }, // ICMT { 0x49474e52, NS_LITERAL_CSTRING("genre") }, // IGNR { 0x494e414d, NS_LITERAL_CSTRING("name") }, // INAM }; const char* const end = chunk.get() + aChunkSize; aTags = new nsHTMLMediaElement::MetadataTags; aTags->Init(); while (p + 8 < end) { uint32_t id = ReadUint32BE(&p); // Uppercase tag id, inspired by GStreamer's Wave parser. id &= 0xDFDFDFDF; uint32_t length = ReadUint32LE(&p); // Subchunk shall not exceed parent chunk. if (p + length > end) { break; } nsCString val(p, length); if (val[length - 1] == '\0') { val.SetLength(length - 1); } // Chunks in List::INFO are always word (two byte) aligned. So round up if // necessary. length += length % 2; p += length; if (!IsUTF8(val)) { continue; } for (size_t i = 0; i < mozilla::ArrayLength(ID_TO_NAME); ++i) { if (id == ID_TO_NAME[i].id) { aTags->Put(ID_TO_NAME[i].name, val); break; } } } return true; }
SECStatus PRNGTEST_RunHealthTests() { static const PRUint8 entropy[] = { 0x8e, 0x9c, 0x0d, 0x25, 0x75, 0x22, 0x04, 0xf9, 0xc5, 0x79, 0x10, 0x8b, 0x23, 0x79, 0x37, 0x14, 0x9f, 0x2c, 0xc7, 0x0b, 0x39, 0xf8, 0xee, 0xef, 0x95, 0x0c, 0x97, 0x59, 0xfc, 0x0a, 0x85, 0x41, 0x76, 0x9d, 0x6d, 0x67, 0x00, 0x4e, 0x19, 0x12, 0x02, 0x16, 0x53, 0xea, 0xf2, 0x73, 0xd7, 0xd6, 0x7f, 0x7e, 0xc8, 0xae, 0x9c, 0x09, 0x99, 0x7d, 0xbb, 0x9e, 0x48, 0x7f, 0xbb, 0x96, 0x46, 0xb3, 0x03, 0x75, 0xf8, 0xc8, 0x69, 0x45, 0x3f, 0x97, 0x5e, 0x2e, 0x48, 0xe1, 0x5d, 0x58, 0x97, 0x4c }; static const PRUint8 rng_known_result[] = { 0x16, 0xe1, 0x8c, 0x57, 0x21, 0xd8, 0xf1, 0x7e, 0x5a, 0xa0, 0x16, 0x0b, 0x7e, 0xa6, 0x25, 0xb4, 0x24, 0x19, 0xdb, 0x54, 0xfa, 0x35, 0x13, 0x66, 0xbb, 0xaa, 0x2a, 0x1b, 0x22, 0x33, 0x2e, 0x4a, 0x14, 0x07, 0x9d, 0x52, 0xfc, 0x73, 0x61, 0x48, 0xac, 0xc1, 0x22, 0xfc, 0xa4, 0xfc, 0xac, 0xa4, 0xdb, 0xda, 0x5b, 0x27, 0x33, 0xc4, 0xb3 }; static const PRUint8 reseed_entropy[] = { 0xc6, 0x0b, 0x0a, 0x30, 0x67, 0x07, 0xf4, 0xe2, 0x24, 0xa7, 0x51, 0x6f, 0x5f, 0x85, 0x3e, 0x5d, 0x67, 0x97, 0xb8, 0x3b, 0x30, 0x9c, 0x7a, 0xb1, 0x52, 0xc6, 0x1b, 0xc9, 0x46, 0xa8, 0x62, 0x79 }; static const PRUint8 additional_input[] = { 0x86, 0x82, 0x28, 0x98, 0xe7, 0xcb, 0x01, 0x14, 0xae, 0x87, 0x4b, 0x1d, 0x99, 0x1b, 0xc7, 0x41, 0x33, 0xff, 0x33, 0x66, 0x40, 0x95, 0x54, 0xc6, 0x67, 0x4d, 0x40, 0x2a, 0x1f, 0xf9, 0xeb, 0x65 }; static const PRUint8 rng_reseed_result[] = { 0x02, 0x0c, 0xc6, 0x17, 0x86, 0x49, 0xba, 0xc4, 0x7b, 0x71, 0x35, 0x05, 0xf0, 0xdb, 0x4a, 0xc2, 0x2c, 0x38, 0xc1, 0xa4, 0x42, 0xe5, 0x46, 0x4a, 0x7d, 0xf0, 0xbe, 0x47, 0x88, 0xb8, 0x0e, 0xc6, 0x25, 0x2b, 0x1d, 0x13, 0xef, 0xa6, 0x87, 0x96, 0xa3, 0x7d, 0x5b, 0x80, 0xc2, 0x38, 0x76, 0x61, 0xc7, 0x80, 0x5d, 0x0f, 0x05, 0x76, 0x85 }; static const PRUint8 rng_no_reseed_result[] = { 0xc4, 0x40, 0x41, 0x8c, 0xbf, 0x2f, 0x70, 0x23, 0x88, 0xf2, 0x7b, 0x30, 0xc3, 0xca, 0x1e, 0xf3, 0xef, 0x53, 0x81, 0x5d, 0x30, 0xed, 0x4c, 0xf1, 0xff, 0x89, 0xa5, 0xee, 0x92, 0xf8, 0xc0, 0x0f, 0x88, 0x53, 0xdf, 0xb6, 0x76, 0xf0, 0xaa, 0xd3, 0x2e, 0x1d, 0x64, 0x37, 0x3e, 0xe8, 0x4a, 0x02, 0xff, 0x0a, 0x7f, 0xe5, 0xe9, 0x2b, 0x6d }; SECStatus rng_status = SECSuccess; PR_STATIC_ASSERT(sizeof(rng_known_result) >= sizeof(rng_reseed_result)); PRUint8 result[sizeof(rng_known_result)]; /********************************************/ /* First test instantiate error path. */ /* In this case we supply enough entropy, */ /* but not enough seed. This will trigger */ /* the code that checks for a entropy */ /* source failure. */ /********************************************/ rng_status = PRNGTEST_Instantiate(entropy, 256 / PR_BITS_PER_BYTE, NULL, 0, NULL, 0); if (rng_status == SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } if (PORT_GetError() != SEC_ERROR_NEED_RANDOM) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } /* we failed with the proper error code, we can continue */ /********************************************/ /* Generate random bytes with a known seed. */ /********************************************/ rng_status = PRNGTEST_Instantiate(entropy, sizeof entropy, NULL, 0, NULL, 0); if (rng_status != SECSuccess) { /* Error set by PRNGTEST_Instantiate */ return SECFailure; } rng_status = PRNGTEST_Generate(result, sizeof rng_known_result, NULL, 0); if ((rng_status != SECSuccess) || (PORT_Memcmp(result, rng_known_result, sizeof rng_known_result) != 0)) { PRNGTEST_Uninstantiate(); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } rng_status = PRNGTEST_Reseed(reseed_entropy, sizeof reseed_entropy, additional_input, sizeof additional_input); if (rng_status != SECSuccess) { /* Error set by PRNG_Reseed */ PRNGTEST_Uninstantiate(); return SECFailure; } rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0); if ((rng_status != SECSuccess) || (PORT_Memcmp(result, rng_reseed_result, sizeof rng_reseed_result) != 0)) { PRNGTEST_Uninstantiate(); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } /* This magic forces the reseed count to it's max count, so we can see if * PRNGTEST_Generate will actually when it reaches it's count */ rng_status = PRNGTEST_Reseed(NULL, 0, NULL, 0); if (rng_status != SECSuccess) { PRNGTEST_Uninstantiate(); /* Error set by PRNG_Reseed */ return SECFailure; } /* This generate should now reseed */ rng_status = PRNGTEST_Generate(result, sizeof rng_reseed_result, NULL, 0); if ((rng_status != SECSuccess) || /* NOTE we fail if the result is equal to the no_reseed_result. * no_reseed_result is the value we would have gotten if we didn't * do an automatic reseed in PRNGTEST_Generate */ (PORT_Memcmp(result, rng_no_reseed_result, sizeof rng_no_reseed_result) == 0)) { PRNGTEST_Uninstantiate(); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } /* make sure reseed fails when we don't supply enough entropy */ rng_status = PRNGTEST_Reseed(reseed_entropy, 4, NULL, 0); if (rng_status == SECSuccess) { PRNGTEST_Uninstantiate(); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } if (PORT_GetError() != SEC_ERROR_NEED_RANDOM) { PRNGTEST_Uninstantiate(); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } rng_status = PRNGTEST_Uninstantiate(); if (rng_status != SECSuccess) { /* Error set by PRNG_Uninstantiate */ return rng_status; } /* make sure uninstantiate fails if the contest is not initiated (also tests * if the context was cleared in the previous Uninstantiate) */ rng_status = PRNGTEST_Uninstantiate(); if (rng_status == SECSuccess) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } if (PORT_GetError() != SEC_ERROR_LIBRARY_FAILURE) { return rng_status; } return SECSuccess; }
/* ** Update the global random number generator with more seeding ** material. */ SECStatus RNG_RandomUpdate(const void *data, size_t bytes) { SECStatus rv; /* Make sure our assumption that size_t is unsigned is true */ PR_STATIC_ASSERT(((size_t)-1) > (size_t)1); #if defined(NS_PTR_GT_32) || (defined(NSS_USE_64) && !defined(NS_PTR_LE_32)) /* * NIST 800-90 requires us to verify our inputs. This value can * come from the application, so we need to make sure it's within the * spec. The spec says it must be less than 2^32 bytes (2^35 bits). * This can only happen if size_t is greater than 32 bits (i.e. on * most 64 bit platforms). The 90% case (perhaps 100% case), size_t * is less than or equal to 32 bits if the platform is not 64 bits, and * greater than 32 bits if it is a 64 bit platform. The corner * cases are handled with explicit defines NS_PTR_GT_32 and NS_PTR_LE_32. * * In general, neither NS_PTR_GT_32 nor NS_PTR_LE_32 will need to be * defined. If you trip over the next two size ASSERTS at compile time, * you will need to define them for your platform. * * if 'sizeof(size_t) > 4' is triggered it means that we were expecting * sizeof(size_t) to be greater than 4, but it wasn't. Setting * NS_PTR_LE_32 will correct that mistake. * * if 'sizeof(size_t) <= 4' is triggered, it means that we were expecting * sizeof(size_t) to be less than or equal to 4, but it wasn't. Setting * NS_PTR_GT_32 will correct that mistake. */ PR_STATIC_ASSERT(sizeof(size_t) > 4); if (bytes > (size_t)PRNG_MAX_ADDITIONAL_BYTES) { bytes = PRNG_MAX_ADDITIONAL_BYTES; } #else PR_STATIC_ASSERT(sizeof(size_t) <= 4); #endif PZ_Lock(globalrng->lock); /* if we're passed more than our additionalDataCache, simply * call reseed with that data */ if (bytes > sizeof(globalrng->additionalDataCache)) { rv = prng_reseed_test(globalrng, NULL, 0, data, (unsigned int)bytes); /* if we aren't going to fill or overflow the buffer, just cache it */ } else if (bytes < ((sizeof globalrng->additionalDataCache) - globalrng->additionalAvail)) { PORT_Memcpy(globalrng->additionalDataCache + globalrng->additionalAvail, data, bytes); globalrng->additionalAvail += (PRUint32)bytes; rv = SECSuccess; } else { /* we are going to fill or overflow the buffer. In this case we will * fill the entropy buffer, reseed with it, start a new buffer with the * remainder. We know the remainder will fit in the buffer because * we already handled the case where bytes > the size of the buffer. */ size_t bufRemain = (sizeof globalrng->additionalDataCache) - globalrng->additionalAvail; /* fill the rest of the buffer */ if (bufRemain) { PORT_Memcpy(globalrng->additionalDataCache + globalrng->additionalAvail, data, bufRemain); data = ((unsigned char *)data) + bufRemain; bytes -= bufRemain; } /* reseed from buffer */ rv = prng_reseed_test(globalrng, NULL, 0, globalrng->additionalDataCache, sizeof globalrng->additionalDataCache); /* copy the rest into the cache */ PORT_Memcpy(globalrng->additionalDataCache, data, bytes); globalrng->additionalAvail = (PRUint32)bytes; } PZ_Unlock(globalrng->lock); return rv; }