void testTHashtable(nsTHashtable<EntityToUnicodeEntry>& hash, uint32_t numEntries) { uint32_t i; for (i = 0; i < numEntries; ++i) { EntityToUnicodeEntry* entry = hash.PutEntry(gEntities[i].mStr); EXPECT_TRUE(entry); EXPECT_FALSE(entry->mNode); entry->mNode = &gEntities[i]; } for (i = 0; i < numEntries; ++i) { EntityToUnicodeEntry* entry = hash.GetEntry(gEntities[i].mStr); EXPECT_TRUE(entry); } EntityToUnicodeEntry* entry = hash.GetEntry("xxxy"); EXPECT_FALSE(entry); uint32_t count = nsTIterPrint(hash); EXPECT_EQ(count, numEntries); }
void testTHashtable(nsTHashtable<EntityToUnicodeEntry>& hash, uint32_t numEntries) { printf("Filling hash with %d entries.\n", numEntries); uint32_t i; for (i = 0; i < numEntries; ++i) { printf(" Putting entry \"%s\"...", gEntities[i].mStr); EntityToUnicodeEntry* entry = hash.PutEntry(gEntities[i].mStr); if (!entry) { printf("FAILED\n"); exit (2); } printf("OK..."); if (entry->mNode) { printf("entry already exists!\n"); exit (3); } printf("\n"); entry->mNode = &gEntities[i]; } printf("Testing Get:\n"); for (i = 0; i < numEntries; ++i) { printf(" Getting entry \"%s\"...", gEntities[i].mStr); EntityToUnicodeEntry* entry = hash.GetEntry(gEntities[i].mStr); if (!entry) { printf("FAILED\n"); exit (4); } printf("Found %u\n", entry->mNode->mUnicode); } printf("Testing nonexistent entries..."); EntityToUnicodeEntry* entry = hash.GetEntry("xxxy"); if (entry) { printf("FOUND! BAD!\n"); exit (5); } printf("not found; good.\n"); printf("Enumerating:\n"); uint32_t count = hash.EnumerateEntries(nsTEnumGo, nullptr); if (count != numEntries) { printf(" Bad count!\n"); exit (6); } }
void TableToArray(const nsTHashtable<nsPtrHashKey<void>>& aTable, nsTArray<void*>& aArray) { uint32_t i = 0; void** elements = aArray.AppendElements(aTable.Count()); for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) { elements[i] = iter.Get()->GetKey(); ++i; } }
static uint32_t nsTIterPrintRemove(nsTHashtable<EntityToUnicodeEntry>& hash) { uint32_t n = 0; for (auto iter = hash.Iter(); !iter.Done(); iter.Next()) { iter.Remove(); n++; } return n; }
void* Allocate(uint32_t aCode, size_t aSize) { NS_ABORT_IF_FALSE(aSize > 0, "PresArena cannot allocate zero bytes"); // We only hand out aligned sizes aSize = PL_ARENA_ALIGN(&mPool, aSize); // If there is no free-list entry for this type already, we have // to create one now, to record its size. FreeList* list = mFreeLists.PutEntry(aCode); nsTArray<void*>::index_type len = list->mEntries.Length(); if (list->mEntrySize == 0) { NS_ABORT_IF_FALSE(len == 0, "list with entries but no recorded size"); list->mEntrySize = aSize; } else { NS_ABORT_IF_FALSE(list->mEntrySize == aSize, "different sizes for same object type code"); } void* result; if (len > 0) { // LIFO behavior for best cache utilization result = list->mEntries.ElementAt(len - 1); list->mEntries.RemoveElementAt(len - 1); #ifdef DEBUG { char* p = reinterpret_cast<char*>(result); char* limit = p + list->mEntrySize; for (; p < limit; p += sizeof(uintptr_t)) { uintptr_t val = *reinterpret_cast<uintptr_t*>(p); NS_ABORT_IF_FALSE(val == ARENA_POISON, nsPrintfCString("PresArena: poison overwritten; " "wanted %.16llx " "found %.16llx " "errors in bits %.16llx", uint64_t(ARENA_POISON), uint64_t(val), uint64_t(ARENA_POISON ^ val) ).get()); } } #endif return result; } // Allocate a new chunk from the arena list->mEntriesEverAllocated++; PL_ARENA_ALLOCATE(result, &mPool, aSize); if (!result) { NS_RUNTIMEABORT("out of memory"); } return result; }
void nsWindowRoot::GetEnabledDisabledCommandsForControllers(nsIControllers* aControllers, nsTHashtable<nsCharPtrHashKey>& aCommandsHandled, nsTArray<nsCString>& aEnabledCommands, nsTArray<nsCString>& aDisabledCommands) { uint32_t controllerCount; aControllers->GetControllerCount(&controllerCount); for (uint32_t c = 0; c < controllerCount; c++) { nsCOMPtr<nsIController> controller; aControllers->GetControllerAt(c, getter_AddRefs(controller)); nsCOMPtr<nsICommandController> commandController(do_QueryInterface(controller)); if (commandController) { uint32_t commandsCount; char** commands; if (NS_SUCCEEDED(commandController->GetSupportedCommands(&commandsCount, &commands))) { for (uint32_t e = 0; e < commandsCount; e++) { // Use a hash to determine which commands have already been handled by // earlier controllers, as the earlier controller's result should get // priority. if (!aCommandsHandled.Contains(commands[e])) { aCommandsHandled.PutEntry(commands[e]); bool enabled = false; controller->IsCommandEnabled(commands[e], &enabled); const nsDependentCSubstring commandStr(commands[e], strlen(commands[e])); if (enabled) { aEnabledCommands.AppendElement(commandStr); } else { aDisabledCommands.AppendElement(commandStr); } } } NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(commandsCount, commands); } } } }
static void LoadSkipSpaceLookupCheck(nsTHashtable<nsStringHashKey>& aSkipSpaceLookupCheck) { nsAutoTArray<nsString, 5> skiplist; gfxFontUtils::GetPrefsFontList( "font.whitelist.skip_default_features_space_check", skiplist); uint32_t numFonts = skiplist.Length(); for (uint32_t i = 0; i < numFonts; i++) { ToLowerCase(skiplist[i]); aSkipSpaceLookupCheck.PutEntry(skiplist[i]); } }
void Free(PRUint32 aCode, void* aPtr) { // Try to recycle this entry. FreeList* list = mFreeLists.GetEntry(aCode); NS_ABORT_IF_FALSE(list, "no free list for pres arena object"); NS_ABORT_IF_FALSE(list->mEntrySize > 0, "PresArena cannot free zero bytes"); char* p = reinterpret_cast<char*>(aPtr); char* limit = p + list->mEntrySize; for (; p < limit; p += sizeof(PRUword)) { *reinterpret_cast<PRUword*>(p) = ARENA_POISON; } list->mEntries.AppendElement(aPtr); }
size_t SizeOfIncludingThisFromMalloc(nsMallocSizeOfFun aMallocSizeOf) const { size_t n = aMallocSizeOf(this); // The first PLArena is within the PLArenaPool, i.e. within |this|, so we // don't measure it. Subsequent PLArenas are by themselves and must be // measured. const PLArena *arena = mPool.first.next; while (arena) { n += aMallocSizeOf(arena); arena = arena->next; } n += mFreeLists.SizeOfExcludingThis(SizeOfFreeListEntryExcludingThis, aMallocSizeOf); return n; }
void* Allocate(PRUint32 aCode, size_t aSize) { NS_ABORT_IF_FALSE(aSize > 0, "PresArena cannot allocate zero bytes"); // We only hand out aligned sizes aSize = PL_ARENA_ALIGN(&mPool, aSize); // If there is no free-list entry for this type already, we have // to create one now, to record its size. FreeList* list = mFreeLists.PutEntry(aCode); if (!list) { return nsnull; } nsTArray<void*>::index_type len = list->mEntries.Length(); if (list->mEntrySize == 0) { NS_ABORT_IF_FALSE(len == 0, "list with entries but no recorded size"); list->mEntrySize = aSize; } else { NS_ABORT_IF_FALSE(list->mEntrySize == aSize, "different sizes for same object type code"); } void* result; if (len > 0) { // LIFO behavior for best cache utilization result = list->mEntries.ElementAt(len - 1); list->mEntries.RemoveElementAt(len - 1); #ifdef DEBUG { char* p = reinterpret_cast<char*>(result); char* limit = p + list->mEntrySize; for (; p < limit; p += sizeof(PRUword)) { NS_ABORT_IF_FALSE(*reinterpret_cast<PRUword*>(p) == ARENA_POISON, "PresArena: poison overwritten"); } } #endif return result; } // Allocate a new chunk from the arena PL_ARENA_ALLOCATE(result, &mPool, aSize); return result; }
void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, nsArenaMemoryStats* aArenaStats) { // We do a complicated dance here because we want to measure the // space taken up by the different kinds of objects in the arena, // but we don't have pointers to those objects. And even if we did, // we wouldn't be able to use aMallocSizeOf on them, since they were // allocated out of malloc'd chunks of memory. So we compute the // size of the arena as known by malloc and we add up the sizes of // all the objects that we care about. Subtracting these two // quantities gives us a catch-all "other" number, which includes // slop in the arena itself as well as the size of objects that // we've not measured explicitly. size_t mallocSize = SizeOfIncludingThisFromMalloc(aMallocSizeOf); EnumerateData data = { aArenaStats, 0 }; mFreeLists.EnumerateEntries(FreeListEnumerator, &data); aArenaStats->mOther = mallocSize - data.total; }
State() { mFreeLists.Init(); PL_INIT_ARENA_POOL(&mPool, "PresArena", ARENA_PAGE_SIZE); PR_CallOnce(&ARENA_POISON_guard, ARENA_POISON_init); }
// recursively check a directory tree for files not in the list of // verified files we found in the manifest. For each file we find // Check it against the files found in the manifest. If the file wasn't // in the manifest then it's unsigned and we can stop looking. Otherwise // remove it from the collection so we can check leftovers later. // // @param aDir Directory to check // @param aPath Relative path to that directory (to check against aItems) // @param aItems All the files found // @param *Filename signature files that won't be in the manifest nsresult CheckDirForUnsignedFiles(nsIFile* aDir, const nsString& aPath, /* in/out */ nsTHashtable<nsStringHashKey>& aItems, const nsAString& sigFilename, const nsAString& sfFilename, const nsAString& mfFilename) { nsCOMPtr<nsISimpleEnumerator> entries; nsresult rv = aDir->GetDirectoryEntries(getter_AddRefs(entries)); nsCOMPtr<nsIDirectoryEnumerator> files = do_QueryInterface(entries); if (NS_FAILED(rv) || !files) { return NS_ERROR_SIGNED_JAR_ENTRY_MISSING; } bool inMeta = StringBeginsWith(aPath, NS_LITERAL_STRING(JAR_META_DIR)); while (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIFile> file; rv = files->GetNextFile(getter_AddRefs(file)); if (NS_FAILED(rv) || !file) { break; } nsAutoString leafname; rv = file->GetLeafName(leafname); if (NS_FAILED(rv)) { return rv; } nsAutoString curName(aPath + leafname); bool isDir; rv = file->IsDirectory(&isDir); if (NS_FAILED(rv)) { return rv; } // if it's a directory we need to recurse if (isDir) { curName.Append(NS_LITERAL_STRING("/")); rv = CheckDirForUnsignedFiles(file, curName, aItems, sigFilename, sfFilename, mfFilename); } else { // The files that comprise the signature mechanism are not covered by the // signature. // // XXX: This is OK for a single signature, but doesn't work for // multiple signatures because the metadata for the other signatures // is not signed either. if (inMeta && ( leafname == sigFilename || leafname == sfFilename || leafname == mfFilename )) { continue; } // make sure the current file was found in the manifest nsStringHashKey* item = aItems.GetEntry(curName); if (!item) { return NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY; } // Remove the item so we can check for leftover items later aItems.RemoveEntry(item); } } files->Close(); return rv; }
// Parses MANIFEST.MF and verifies the contents of the unpacked files // listed in the manifest. // The filenames of all entries will be returned in aMfItems. aBuf must // be a pre-allocated scratch buffer that is used for doing I/O. nsresult ParseMFUnpacked(const char* aFilebuf, nsIFile* aDir, /*out*/ nsTHashtable<nsStringHashKey>& aMfItems, ScopedAutoSECItem& aBuf) { nsresult rv; const char* nextLineStart = aFilebuf; rv = CheckManifestVersion(nextLineStart, NS_LITERAL_CSTRING(JAR_MF_HEADER)); if (NS_FAILED(rv)) { return rv; } // Skip the rest of the header section, which ends with a blank line. { nsAutoCString line; do { rv = ReadLine(nextLineStart, line); if (NS_FAILED(rv)) { return rv; } } while (line.Length() > 0); // Manifest containing no file entries is OK, though useless. if (*nextLineStart == '\0') { return NS_OK; } } nsAutoString curItemName; ScopedAutoSECItem digest; for (;;) { nsAutoCString curLine; rv = ReadLine(nextLineStart, curLine); if (NS_FAILED(rv)) { return rv; } if (curLine.Length() == 0) { // end of section (blank line or end-of-file) if (curItemName.Length() == 0) { // '...Each section must start with an attribute with the name as // "Name",...', so every section must have a Name attribute. return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID; } if (digest.len == 0) { // We require every entry to have a digest, since we require every // entry to be signed and we don't allow duplicate entries. return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID; } if (aMfItems.Contains(curItemName)) { // Duplicate entry return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID; } // Verify that the file's content digest matches the digest from this // MF section. rv = VerifyFileContentDigest(aDir, curItemName, digest, aBuf); if (NS_FAILED(rv)) { return rv; } aMfItems.PutEntry(curItemName); if (*nextLineStart == '\0') { // end-of-file break; } // reset so we know we haven't encountered either of these for the next // item yet. curItemName.Truncate(); digest.reset(); continue; // skip the rest of the loop below } nsAutoCString attrName; nsAutoCString attrValue; rv = ParseAttribute(curLine, attrName, attrValue); if (NS_FAILED(rv)) { return rv; } // Lines to look for: // (1) Digest: if (attrName.LowerCaseEqualsLiteral("sha1-digest")) { if (digest.len > 0) { // multiple SHA1 digests in section return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID; } rv = MapSECStatus(ATOB_ConvertAsciiToItem(&digest, attrValue.get())); if (NS_FAILED(rv)) { return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID; } continue; } // (2) Name: associates this manifest section with a file in the jar. if (attrName.LowerCaseEqualsLiteral("name")) { if (MOZ_UNLIKELY(curItemName.Length() > 0)) { // multiple names in section return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID; } if (MOZ_UNLIKELY(attrValue.Length() == 0)) { return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID; } curItemName = NS_ConvertUTF8toUTF16(attrValue); continue; } // (3) Magic: the only other must-understand attribute if (attrName.LowerCaseEqualsLiteral("magic")) { // We don't understand any magic, so we can't verify an entry that // requires magic. Since we require every entry to have a valid // signature, we have no choice but to reject the entry. return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID; } // unrecognized attributes must be ignored } return NS_OK; }
static void GetHashtableElements(nsTHashtable<nsPtrHashKey<T> >& aHashtable, nsTArray<T*>& aArray) { aHashtable.EnumerateEntries(&GetHashtableEntry<T>, &aArray); }