test_cookies_chips_purge_crash.js (5260B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 add_setup(function test_setup() { 5 Services.prefs.setIntPref( 6 "network.cookie.cookieBehavior", 7 Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN 8 ); 9 Services.prefs.setBoolPref( 10 "network.cookieJarSettings.unblocked_for_testing", 11 true 12 ); 13 Services.prefs.setBoolPref( 14 "network.cookie.cookieBehavior.optInPartitioning", 15 true 16 ); 17 Services.prefs.setBoolPref("network.cookie.CHIPS.enabled", true); 18 Services.prefs.setBoolPref( 19 "network.cookie.chips.partitionLimitEnabled", 20 true 21 ); 22 Services.prefs.setBoolPref( 23 "network.cookie.chips.partitionLimitDryRun", 24 false 25 ); 26 Services.prefs.setIntPref( 27 "network.cookie.chips.partitionLimitByteCapacity", 28 24 29 ); 30 }); 31 32 registerCleanupFunction(() => { 33 Services.prefs.clearUserPref("network.cookie.cookieBehavior"); 34 Services.prefs.clearUserPref( 35 "network.cookie.cookieBehavior.optInPartitioning" 36 ); 37 Services.prefs.clearUserPref( 38 "network.cookieJarSettings.unblocked_for_testing" 39 ); 40 Services.prefs.clearUserPref("network.cookie.CHIPS.enabled"); 41 Services.prefs.clearUserPref("network.cookie.chips.partitionLimitEnabled"); 42 Services.prefs.clearUserPref("network.cookie.chips.partitionLimitDryRun"); 43 Services.prefs.clearUserPref( 44 "network.cookie.chips.partitionLimitByteCapacity" 45 ); 46 Services.cookies.removeAll(); 47 }); 48 49 function addChipsCookie( 50 name, 51 value, 52 host, 53 expiry, 54 lastAccessed, 55 creationTime, 56 db 57 ) { 58 let cookie = new Cookie( 59 name, 60 value, 61 host, 62 "/", // path 63 expiry, 64 lastAccessed, 65 creationTime, 66 false, // session 67 true, // secure 68 false, // http-only 69 false, // in browser element 70 { partitionKey: "(https,example.com)" }, 71 Ci.nsICookie.SAMESITE_UNSET, 72 Ci.nsICookie.SCHEME_UNSET, 73 true // isPartitioned 74 ); 75 db.insertCookie(cookie); 76 } 77 78 add_task(async function test_purge_crash() { 79 let profile = do_get_profile(); 80 let dbFile = do_get_cookie_file(profile); 81 Assert.ok(!dbFile.exists()); 82 83 let schemaDb = new CookieDatabaseConnection(dbFile, 15); 84 let now = Date.now() * 1000; // date in microseconds 85 let past = Math.round(now / 1e3 - 1000); 86 let future = Math.round(now / 1e3 + 1000) + 20000; 87 let host = "example.com"; 88 89 // add three cookies such that their order in the CookieEntry list is NOT 90 // sorted by age 91 // we set up a few cookies to get close to the chips limit, without going over 92 // if we front-load the list with enough recently used cookies 93 // we can trigger a crash in the CHIPS purging (before our fix in Bug 1971595) 94 addChipsCookie("c4", "4", host, future, past + 4000, past, schemaDb); 95 addChipsCookie("c5", "5", host, future, past + 4000, past, schemaDb); 96 addChipsCookie("c6", "6", host, future, past + 4000, past, schemaDb); 97 addChipsCookie("c7", "7", host, future, past + 4000, past, schemaDb); 98 addChipsCookie("c8", "8", host, future, past + 4000, past, schemaDb); 99 addChipsCookie("c1", "1", host, future, past, past, schemaDb); 100 addChipsCookie("c2", "2", host, future, past + 3000, past, schemaDb); 101 addChipsCookie("c3", "3", host, future, past + 2000, past, schemaDb); 102 103 // check that the cookies were added to the db 104 Assert.equal(do_count_cookies_in_db(schemaDb.db), 8); // total 105 Assert.equal( 106 do_count_cookies_in_db(schemaDb.db, "example.com"), // per host+OA 107 8 108 ); 109 110 const PATH_EMPTY = "/"; 111 const FIRST_PARTY = "example.com"; 112 const URL_DOCUMENT_FIRSTPARTY = "https://" + FIRST_PARTY + PATH_EMPTY; 113 114 function createPartitionKey(url) { 115 let uri = NetUtil.newURI(url); 116 return `(${uri.scheme},${uri.host})`; 117 } 118 function createOriginAttributes(partitionKey) { 119 return JSON.stringify({ 120 firstPartyDomain: "", 121 geckoViewSessionContextId: "", 122 inIsolatedMozBrowser: false, 123 partitionKey, 124 privateBrowsingId: 0, 125 userContextId: 0, 126 }); 127 } 128 const partitionedOAs = createOriginAttributes( 129 createPartitionKey(URL_DOCUMENT_FIRSTPARTY) 130 ); 131 132 // validate the db is as expected 133 // startup the cookie service and check the cookie count 134 // this shouldn't update the lastAccessed values (which determines cookie age) 135 let partitioned = Services.cookies.getCookiesWithOriginAttributes( 136 partitionedOAs, 137 FIRST_PARTY 138 ); 139 // a printed list at this point is expected: c4, c5, ..., c8, c1, ... 140 Assert.equal(partitioned.length, 8); 141 142 // add a CHIPS cookie - triggers a CHIPS purge 143 // use enough Bytes to trigger the purging of many cookies added before 144 // this is where the crash occurs 145 const cv = Services.cookies.add( 146 host, 147 "/", // path 148 "cxxxxx", // name 149 "yyyyyy", // value 150 true, // secure 151 false, // http-only 152 true, // isSession 153 future, 154 { partitionKey: "(https,example.com)" }, 155 Ci.nsICookie.SAMESITE_UNSET, // SameSite 156 Ci.nsICookie.SCHEME_HTTPS, 157 true // partitioned 158 ); 159 Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie"); 160 161 // check post-purge cookie count 162 let postPurgeCookies = Services.cookies.getCookiesWithOriginAttributes( 163 partitionedOAs, 164 FIRST_PARTY 165 ); 166 Assert.equal(postPurgeCookies.length, 5); 167 schemaDb.close(); 168 });