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 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* |
michael@0 | 7 | * |
michael@0 | 8 | * Date: 15 July 2002 |
michael@0 | 9 | * SUMMARY: Testing identifiers with double-byte names |
michael@0 | 10 | * See http://bugzilla.mozilla.org/show_bug.cgi?id=58274 |
michael@0 | 11 | * |
michael@0 | 12 | * Here is a sample of the problem: |
michael@0 | 13 | * |
michael@0 | 14 | * js> function f\u02B1 () {} |
michael@0 | 15 | * |
michael@0 | 16 | * js> f\u02B1.toSource(); |
michael@0 | 17 | * function f¦() {} |
michael@0 | 18 | * |
michael@0 | 19 | * js> f\u02B1.toSource().toSource(); |
michael@0 | 20 | * (new String("function f\xB1() {}")) |
michael@0 | 21 | * |
michael@0 | 22 | * |
michael@0 | 23 | * See how the high-byte information (the 02) has been lost? |
michael@0 | 24 | * The same thing was happening with the toString() method: |
michael@0 | 25 | * |
michael@0 | 26 | * js> f\u02B1.toString(); |
michael@0 | 27 | * |
michael@0 | 28 | * function f¦() { |
michael@0 | 29 | * } |
michael@0 | 30 | * |
michael@0 | 31 | * js> f\u02B1.toString().toSource(); |
michael@0 | 32 | * (new String("\nfunction f\xB1() {\n}\n")) |
michael@0 | 33 | * |
michael@0 | 34 | */ |
michael@0 | 35 | //----------------------------------------------------------------------------- |
michael@0 | 36 | var UBound = 0; |
michael@0 | 37 | var BUGNUMBER = 58274; |
michael@0 | 38 | var summary = 'Testing identifiers with double-byte names'; |
michael@0 | 39 | var status = ''; |
michael@0 | 40 | var statusitems = []; |
michael@0 | 41 | var actual = ''; |
michael@0 | 42 | var actualvalues = []; |
michael@0 | 43 | var expect= ''; |
michael@0 | 44 | var expectedvalues = []; |
michael@0 | 45 | |
michael@0 | 46 | |
michael@0 | 47 | /* |
michael@0 | 48 | * Define a function that uses double-byte identifiers in |
michael@0 | 49 | * "every possible way" |
michael@0 | 50 | * |
michael@0 | 51 | * Then recover each double-byte identifier via f.toString(). |
michael@0 | 52 | * To make this easier, put a 'Z' token before every one. |
michael@0 | 53 | * |
michael@0 | 54 | * Our eval string will be: |
michael@0 | 55 | * |
michael@0 | 56 | * sEval = "function Z\u02b1(Z\u02b2, b) { |
michael@0 | 57 | * try { Z\u02b3 : var Z\u02b4 = Z\u02b1; } |
michael@0 | 58 | * catch (Z\u02b5) { for (var Z\u02b6 in Z\u02b5) |
michael@0 | 59 | * {for (1; 1<0; Z\u02b7++) {new Array()[Z\u02b6] = 1;} };} }"; |
michael@0 | 60 | * |
michael@0 | 61 | * It will be helpful to build this string in stages: |
michael@0 | 62 | */ |
michael@0 | 63 | var s0 = 'function Z'; |
michael@0 | 64 | var s1 = '\u02b1(Z'; |
michael@0 | 65 | var s2 = '\u02b2, b) {try { Z'; |
michael@0 | 66 | var s3 = '\u02b3 : var Z'; |
michael@0 | 67 | var s4 = '\u02b4 = Z'; |
michael@0 | 68 | var s5 = '\u02b1; } catch (Z' |
michael@0 | 69 | var s6 = '\u02b5) { for (var Z'; |
michael@0 | 70 | var s7 = '\u02b6 in Z'; |
michael@0 | 71 | var s8 = '\u02b5){for (1; 1<0; Z'; |
michael@0 | 72 | var s9 = '\u02b7++) {new Array()[Z'; |
michael@0 | 73 | var s10 = '\u02b6] = 1;} };} }'; |
michael@0 | 74 | |
michael@0 | 75 | |
michael@0 | 76 | /* |
michael@0 | 77 | * Concatenate these and eval() to create the function Z\u02b1 |
michael@0 | 78 | */ |
michael@0 | 79 | var sEval = s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10; |
michael@0 | 80 | eval(sEval); |
michael@0 | 81 | |
michael@0 | 82 | |
michael@0 | 83 | /* |
michael@0 | 84 | * Recover all the double-byte identifiers via Z\u02b1.toString(). |
michael@0 | 85 | * We'll recover the 1st one as arrID[1], the 2nd one as arrID[2], |
michael@0 | 86 | * and so on ... |
michael@0 | 87 | */ |
michael@0 | 88 | var arrID = getIdentifiers(Z\u02b1); |
michael@0 | 89 | |
michael@0 | 90 | |
michael@0 | 91 | /* |
michael@0 | 92 | * Now check that we got back what we put in - |
michael@0 | 93 | */ |
michael@0 | 94 | status = inSection(1); |
michael@0 | 95 | actual = arrID[1]; |
michael@0 | 96 | expect = s1.charAt(0); |
michael@0 | 97 | addThis(); |
michael@0 | 98 | |
michael@0 | 99 | status = inSection(2); |
michael@0 | 100 | actual = arrID[2]; |
michael@0 | 101 | expect = s2.charAt(0); |
michael@0 | 102 | addThis(); |
michael@0 | 103 | |
michael@0 | 104 | status = inSection(3); |
michael@0 | 105 | actual = arrID[3]; |
michael@0 | 106 | expect = s3.charAt(0); |
michael@0 | 107 | addThis(); |
michael@0 | 108 | |
michael@0 | 109 | status = inSection(4); |
michael@0 | 110 | actual = arrID[4]; |
michael@0 | 111 | expect = s4.charAt(0); |
michael@0 | 112 | addThis(); |
michael@0 | 113 | |
michael@0 | 114 | status = inSection(5); |
michael@0 | 115 | actual = arrID[5]; |
michael@0 | 116 | expect = s5.charAt(0); |
michael@0 | 117 | addThis(); |
michael@0 | 118 | |
michael@0 | 119 | status = inSection(6); |
michael@0 | 120 | actual = arrID[6]; |
michael@0 | 121 | expect = s6.charAt(0); |
michael@0 | 122 | addThis(); |
michael@0 | 123 | |
michael@0 | 124 | status = inSection(7); |
michael@0 | 125 | actual = arrID[7]; |
michael@0 | 126 | expect = s7.charAt(0); |
michael@0 | 127 | addThis(); |
michael@0 | 128 | |
michael@0 | 129 | status = inSection(8); |
michael@0 | 130 | actual = arrID[8]; |
michael@0 | 131 | expect = s8.charAt(0); |
michael@0 | 132 | addThis(); |
michael@0 | 133 | |
michael@0 | 134 | status = inSection(9); |
michael@0 | 135 | actual = arrID[9]; |
michael@0 | 136 | expect = s9.charAt(0); |
michael@0 | 137 | addThis(); |
michael@0 | 138 | |
michael@0 | 139 | status = inSection(10); |
michael@0 | 140 | actual = arrID[10]; |
michael@0 | 141 | expect = s10.charAt(0); |
michael@0 | 142 | addThis(); |
michael@0 | 143 | |
michael@0 | 144 | |
michael@0 | 145 | |
michael@0 | 146 | |
michael@0 | 147 | //----------------------------------------------------------------------------- |
michael@0 | 148 | test(); |
michael@0 | 149 | //----------------------------------------------------------------------------- |
michael@0 | 150 | |
michael@0 | 151 | |
michael@0 | 152 | |
michael@0 | 153 | /* |
michael@0 | 154 | * Goal: recover the double-byte identifiers from f.toString() |
michael@0 | 155 | * by getting the very next character after each 'Z' token. |
michael@0 | 156 | * |
michael@0 | 157 | * The return value will be an array |arr| indexed such that |
michael@0 | 158 | * |arr[1]| is the 1st identifier, |arr[2]| the 2nd, and so on. |
michael@0 | 159 | * |
michael@0 | 160 | * Note, however, f.toString() is implementation-independent. |
michael@0 | 161 | * For example, it may begin with '\nfunction' instead of 'function'. |
michael@0 | 162 | * |
michael@0 | 163 | * Rhino uses a Unicode representation for f.toString(); whereas |
michael@0 | 164 | * SpiderMonkey uses an ASCII representation, putting escape sequences |
michael@0 | 165 | * for non-ASCII characters. For example, if a function is called f\u02B1, |
michael@0 | 166 | * then in Rhino the toString() method will present a 2-character Unicode |
michael@0 | 167 | * string for its name, whereas SpiderMonkey will present a 7-character |
michael@0 | 168 | * ASCII string for its name: the string literal 'f\u02B1'. |
michael@0 | 169 | * |
michael@0 | 170 | * So we force the lexer to condense the string before we use it. |
michael@0 | 171 | * This will give uniform results in Rhino and SpiderMonkey. |
michael@0 | 172 | */ |
michael@0 | 173 | function getIdentifiers(f) |
michael@0 | 174 | { |
michael@0 | 175 | var str = condenseStr(f.toString()); |
michael@0 | 176 | var arr = str.split('Z'); |
michael@0 | 177 | |
michael@0 | 178 | /* |
michael@0 | 179 | * The identifiers are the 1st char of each split substring |
michael@0 | 180 | * EXCEPT the first one, which is just ('\n' +) 'function '. |
michael@0 | 181 | * |
michael@0 | 182 | * Thus note the 1st identifier will be stored in |arr[1]|, |
michael@0 | 183 | * the 2nd one in |arr[2]|, etc., making the indexing easy - |
michael@0 | 184 | */ |
michael@0 | 185 | for (i in arr) |
michael@0 | 186 | arr[i] = arr[i].charAt(0); |
michael@0 | 187 | return arr; |
michael@0 | 188 | } |
michael@0 | 189 | |
michael@0 | 190 | |
michael@0 | 191 | /* |
michael@0 | 192 | * This function is the opposite of a functions like escape(), which take |
michael@0 | 193 | * Unicode characters and return escape sequences for them. Here, we force |
michael@0 | 194 | * the lexer to turn escape sequences back into single characters. |
michael@0 | 195 | * |
michael@0 | 196 | * Note we can't simply do |eval(str)|, since in practice |str| will be an |
michael@0 | 197 | * identifier somewhere in the program (e.g. a function name); thus |eval(str)| |
michael@0 | 198 | * would return the object that the identifier represents: not what we want. |
michael@0 | 199 | * |
michael@0 | 200 | * So we surround |str| lexicographically with quotes to force the lexer to |
michael@0 | 201 | * evaluate it as a string. Have to strip out any linefeeds first, however - |
michael@0 | 202 | */ |
michael@0 | 203 | function condenseStr(str) |
michael@0 | 204 | { |
michael@0 | 205 | /* |
michael@0 | 206 | * You won't be able to do the next step if |str| has |
michael@0 | 207 | * any carriage returns or linefeeds in it. For example: |
michael@0 | 208 | * |
michael@0 | 209 | * js> eval("'" + '\nHello' + "'"); |
michael@0 | 210 | * 1: SyntaxError: unterminated string literal: |
michael@0 | 211 | * 1: ' |
michael@0 | 212 | * 1: ^ |
michael@0 | 213 | * |
michael@0 | 214 | * So replace them with the empty string - |
michael@0 | 215 | */ |
michael@0 | 216 | str = str.replace(/[\r\n]/g, '') |
michael@0 | 217 | return eval("'" + str + "'") |
michael@0 | 218 | } |
michael@0 | 219 | |
michael@0 | 220 | |
michael@0 | 221 | function addThis() |
michael@0 | 222 | { |
michael@0 | 223 | statusitems[UBound] = status; |
michael@0 | 224 | actualvalues[UBound] = actual; |
michael@0 | 225 | expectedvalues[UBound] = expect; |
michael@0 | 226 | UBound++; |
michael@0 | 227 | } |
michael@0 | 228 | |
michael@0 | 229 | |
michael@0 | 230 | function test() |
michael@0 | 231 | { |
michael@0 | 232 | enterFunc('test'); |
michael@0 | 233 | printBugNumber(BUGNUMBER); |
michael@0 | 234 | printStatus(summary); |
michael@0 | 235 | |
michael@0 | 236 | for (var i=0; i<UBound; i++) |
michael@0 | 237 | { |
michael@0 | 238 | reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); |
michael@0 | 239 | } |
michael@0 | 240 | |
michael@0 | 241 | exitFunc ('test'); |
michael@0 | 242 | } |