Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include <stdio.h> |
michael@0 | 8 | #include "pldhash.h" |
michael@0 | 9 | |
michael@0 | 10 | // pldhash is very widely used and so any basic bugs in it are likely to be |
michael@0 | 11 | // exposed through normal usage. Therefore, this test currently focusses on |
michael@0 | 12 | // extreme cases relating to maximum table capacity and potential overflows, |
michael@0 | 13 | // which are unlikely to be hit during normal execution. |
michael@0 | 14 | |
michael@0 | 15 | namespace TestPLDHash { |
michael@0 | 16 | |
michael@0 | 17 | static bool test_pldhash_Init_capacity_ok() |
michael@0 | 18 | { |
michael@0 | 19 | // Try the largest allowed capacity. With PL_DHASH_MAX_SIZE==1<<26, this |
michael@0 | 20 | // will allocate 0.5GB of entry store on 32-bit platforms and 1GB on 64-bit |
michael@0 | 21 | // platforms. |
michael@0 | 22 | PLDHashTable t; |
michael@0 | 23 | bool ok = PL_DHashTableInit(&t, PL_DHashGetStubOps(), nullptr, |
michael@0 | 24 | sizeof(PLDHashEntryStub), PL_DHASH_MAX_SIZE, |
michael@0 | 25 | mozilla::fallible_t()); |
michael@0 | 26 | if (ok) |
michael@0 | 27 | PL_DHashTableFinish(&t); |
michael@0 | 28 | |
michael@0 | 29 | return ok; |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | static bool test_pldhash_Init_capacity_too_large() |
michael@0 | 33 | { |
michael@0 | 34 | // Try the smallest too-large capacity. |
michael@0 | 35 | PLDHashTable t; |
michael@0 | 36 | bool ok = PL_DHashTableInit(&t, PL_DHashGetStubOps(), nullptr, |
michael@0 | 37 | sizeof(PLDHashEntryStub), PL_DHASH_MAX_SIZE + 1, |
michael@0 | 38 | mozilla::fallible_t()); |
michael@0 | 39 | // Don't call PL_DHashTableDestroy(), it's not safe after Init failure. |
michael@0 | 40 | |
michael@0 | 41 | return !ok; // expected to fail |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | static bool test_pldhash_Init_overflow() |
michael@0 | 45 | { |
michael@0 | 46 | // Try an acceptable capacity, but one whose byte size overflows uint32_t. |
michael@0 | 47 | // |
michael@0 | 48 | // Ideally we'd also try a large-but-ok capacity that almost but doesn't |
michael@0 | 49 | // quite overflow, but that would result in allocating just under 4GB of |
michael@0 | 50 | // entry storage. That's very likely to fail on 32-bit platforms, so such a |
michael@0 | 51 | // test wouldn't be reliable. |
michael@0 | 52 | |
michael@0 | 53 | struct OneKBEntry { |
michael@0 | 54 | PLDHashEntryHdr hdr; |
michael@0 | 55 | char buf[1024 - sizeof(PLDHashEntryHdr)]; |
michael@0 | 56 | }; |
michael@0 | 57 | |
michael@0 | 58 | // |nullptr| for |ops| is ok because it's unused due to the failure. |
michael@0 | 59 | PLDHashTable t; |
michael@0 | 60 | bool ok = PL_DHashTableInit(&t, /* ops = */nullptr, nullptr, |
michael@0 | 61 | sizeof(OneKBEntry), PL_DHASH_MAX_SIZE, |
michael@0 | 62 | mozilla::fallible_t()); |
michael@0 | 63 | |
michael@0 | 64 | return !ok; // expected to fail |
michael@0 | 65 | } |
michael@0 | 66 | |
michael@0 | 67 | // See bug 931062, we skip this test on Android due to OOM. |
michael@0 | 68 | #ifndef MOZ_WIDGET_ANDROID |
michael@0 | 69 | // We insert the integers 0.., so this is has function is (a) as simple as |
michael@0 | 70 | // possible, and (b) collision-free. Both of which are good, because we want |
michael@0 | 71 | // this test to be as fast as possible. |
michael@0 | 72 | static PLDHashNumber |
michael@0 | 73 | hash(PLDHashTable *table, const void *key) |
michael@0 | 74 | { |
michael@0 | 75 | return (PLDHashNumber)(size_t)key; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | static bool test_pldhash_grow_to_max_capacity() |
michael@0 | 79 | { |
michael@0 | 80 | static const PLDHashTableOps ops = { |
michael@0 | 81 | PL_DHashAllocTable, |
michael@0 | 82 | PL_DHashFreeTable, |
michael@0 | 83 | hash, |
michael@0 | 84 | PL_DHashMatchEntryStub, |
michael@0 | 85 | PL_DHashMoveEntryStub, |
michael@0 | 86 | PL_DHashClearEntryStub, |
michael@0 | 87 | PL_DHashFinalizeStub, |
michael@0 | 88 | nullptr |
michael@0 | 89 | }; |
michael@0 | 90 | |
michael@0 | 91 | PLDHashTable t; |
michael@0 | 92 | bool ok = PL_DHashTableInit(&t, &ops, nullptr, sizeof(PLDHashEntryStub), 256, |
michael@0 | 93 | mozilla::fallible_t()); |
michael@0 | 94 | if (!ok) |
michael@0 | 95 | return false; |
michael@0 | 96 | |
michael@0 | 97 | // Keep inserting elements until failure occurs because the table is full. |
michael@0 | 98 | size_t numInserted = 0; |
michael@0 | 99 | while (true) { |
michael@0 | 100 | if (!PL_DHashTableOperate(&t, (const void*)numInserted, PL_DHASH_ADD)) { |
michael@0 | 101 | break; |
michael@0 | 102 | } |
michael@0 | 103 | numInserted++; |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | // We stop when the element count is 96.875% of PL_DHASH_MAX_SIZE (see |
michael@0 | 107 | // MaxLoadOnGrowthFailure()). |
michael@0 | 108 | return numInserted == PL_DHASH_MAX_SIZE - (PL_DHASH_MAX_SIZE >> 5); |
michael@0 | 109 | } |
michael@0 | 110 | #endif |
michael@0 | 111 | |
michael@0 | 112 | //---- |
michael@0 | 113 | |
michael@0 | 114 | typedef bool (*TestFunc)(); |
michael@0 | 115 | #define DECL_TEST(name) { #name, name } |
michael@0 | 116 | |
michael@0 | 117 | static const struct Test { |
michael@0 | 118 | const char* name; |
michael@0 | 119 | TestFunc func; |
michael@0 | 120 | } tests[] = { |
michael@0 | 121 | DECL_TEST(test_pldhash_Init_capacity_ok), |
michael@0 | 122 | DECL_TEST(test_pldhash_Init_capacity_too_large), |
michael@0 | 123 | DECL_TEST(test_pldhash_Init_overflow), |
michael@0 | 124 | // See bug 931062, we skip this test on Android due to OOM. |
michael@0 | 125 | #ifndef MOZ_WIDGET_ANDROID |
michael@0 | 126 | DECL_TEST(test_pldhash_grow_to_max_capacity), |
michael@0 | 127 | #endif |
michael@0 | 128 | { nullptr, nullptr } |
michael@0 | 129 | }; |
michael@0 | 130 | |
michael@0 | 131 | } // namespace TestPLDHash |
michael@0 | 132 | |
michael@0 | 133 | using namespace TestPLDHash; |
michael@0 | 134 | |
michael@0 | 135 | int main(int argc, char *argv[]) |
michael@0 | 136 | { |
michael@0 | 137 | bool success = true; |
michael@0 | 138 | for (const Test* t = tests; t->name != nullptr; ++t) { |
michael@0 | 139 | bool test_result = t->func(); |
michael@0 | 140 | printf("%25s : %s\n", t->name, test_result ? "SUCCESS" : "FAILURE"); |
michael@0 | 141 | if (!test_result) |
michael@0 | 142 | success = false; |
michael@0 | 143 | } |
michael@0 | 144 | return success ? 0 : -1; |
michael@0 | 145 | } |