File indexing completed on 2024-04-28 15:28:37
0001 /* 0002 0003 var enc = encodeURI; 0004 var dec = decodeURI; 0005 //var enc = encodeURIComponent; 0006 //var dec = decodeURIComponent; 0007 0008 function printstr(i,j) 0009 { 0010 var str; 0011 if (j == undefined) 0012 str = "x"+String.fromCharCode(i)+"x"; 0013 else 0014 str = "x"+String.fromCharCode(i)+String.fromCharCode(j)+"x"; 0015 var encoded = "(exception)"; 0016 var decoded = "(unknown)"; 0017 try { 0018 encoded = enc(str); 0019 decoded = "(exception)"; 0020 decoded = dec(encoded); 0021 } 0022 catch (e) { 0023 } 0024 0025 var prefix = i; 0026 if (j != undefined) 0027 prefix += "/" + j; 0028 0029 var match; 0030 if (encoded == "(exception)" || decoded == "(exception)") 0031 match = ""; 0032 else if (str == decoded) 0033 match = " (match)"; 0034 else 0035 match = " (nomatch)"; 0036 0037 print(prefix+": encoded "+encoded+" decoded "+decoded+" "+match); 0038 } 0039 0040 for (var charcode = 0; charcode <= 0xFFFF; charcode++) 0041 printstr(charcode); 0042 0043 for (var charcode = 0xDC00; charcode <= 0xDFFF; charcode++) 0044 printstr(0xD800,charcode); 0045 0046 for (var charcode = 0xD800; charcode <= 0xDBFF; charcode++) 0047 printstr(charcode,0xD800); 0048 0049 */ 0050 0051 // -------------------------------------------------------------------------------- 0052 0053 var resolution = 13; // set to 1 for 100% coverage 0054 0055 function checkEncodeException(encodeFunction,c1,c2) 0056 { 0057 var str; 0058 if (c2 == undefined) 0059 str = "x"+String.fromCharCode(c1)+"x"; 0060 else 0061 str = "x"+String.fromCharCode(c1)+String.fromCharCode(c2)+"x"; 0062 0063 try { 0064 encodeFunction(str); 0065 // print("checkEncodeException("+c1+","+c2+"): false"); 0066 return false; 0067 } 0068 catch (e) { 0069 // print("checkEncodeException("+c1+","+c2+"): true"); 0070 return true; 0071 } 0072 } 0073 0074 function checkEncodeDecode(encodeFunction,decodeFunction,c1,c2) 0075 { 0076 var str; 0077 if (c2 == undefined) 0078 str = "x"+String.fromCharCode(c1)+"x"; 0079 else 0080 str = "x"+String.fromCharCode(c1)+String.fromCharCode(c2)+"x"; 0081 0082 try { 0083 var encoded = encodeFunction(str); 0084 var decoded = decodeFunction(encoded); 0085 0086 // print("checkEncodeDecode("+c1+","+c2+"): "+(str == decoded)); 0087 if (str != decoded) { 0088 debug("Encode/Decode mismatch with c1:" + c1 + " c2:" + c2); 0089 debug("input: " + str); 0090 debug("encoded:" + encoded); 0091 debug("decoded:" + decoded); 0092 for (var i = 0; i < decoded.length; ++i) 0093 debug("at pos:" + i + " " + decoded.charCodeAt(i)); 0094 } 0095 return (str == decoded); 0096 } 0097 catch (e) { 0098 debug("Exception with c1:" + c1 + " c2:" + c2); 0099 // print("checkEncodeDecode("+c1+","+c2+"): false (exception)"); 0100 return false; 0101 } 0102 } 0103 0104 /********* disabled because of conflicts *********** 0105 0106 function checkWithFunctions(encodeFunction,decodeFunction) 0107 { 0108 var passes = 0; 0109 var failures = 0; 0110 var totalFailures = 0; 0111 0112 // 0-0xD800 and 0xDC00-0xFFFF 0113 0114 for (var charcode = 0; charcode < 0xD800; charcode += resolution) { 0115 if (checkEncodeDecode(encodeFunction,decodeFunction,charcode)) 0116 passes++; 0117 else 0118 failures++; 0119 } 0120 0121 debug("0x0000 - 0xD7FF range, passes:" + passes + ", failures:" + failures); 0122 0123 totalFailures += failures; 0124 failures = 0; 0125 passes = 0; 0126 0127 for (var charcode = 0xE000; charcode <= 0xFFFF; charcode += resolution) { 0128 if (checkEncodeDecode(encodeFunction,decodeFunction,charcode)) 0129 passes++; 0130 else 0131 failures++; 0132 } 0133 0134 debug("0xE000 - 0xFFFF range, passes:" + passes + ", failures:" + failures); 0135 totalFailures += failures; 0136 failures = 0; 0137 passes = 0; 0138 0139 // 0xDC00-0xDFFF 0140 for (var charcode = 0xDC00; charcode <= 0xDFFF; charcode += resolution) { 0141 if (checkEncodeException(encodeFunction,charcode)) 0142 passes++; 0143 else 0144 failures++; 0145 } 0146 0147 debug("0xDC00 - 0xDFFF range (expected exception), passes:" + passes + ", failures:" + failures); 0148 totalFailures += failures; 0149 failures = 0; 0150 passes = 0; 0151 0152 0153 // 0xD800-0xDBFF followed by 0xDC00-0xDFFF 0154 0155 for (var charcode = 0xD800; charcode < 0xDC00; charcode += resolution) { 0156 if (checkEncodeDecode(encodeFunction,decodeFunction,charcode,0xDC00)) 0157 passes++; 0158 else 0159 failures++; 0160 } 0161 0162 for (var charcode = 0xDC00; charcode < 0xE000; charcode += resolution) { 0163 if (checkEncodeDecode(encodeFunction,decodeFunction,0xD800,charcode)) 0164 passes++; 0165 else 0166 failures++; 0167 } 0168 0169 debug("Surrogate pairs test, passes:" + passes + ", failures:" + failures); 0170 totalFailures += failures; 0171 failures = 0; 0172 passes = 0; 0173 0174 // 0xD800-0xDBFF _not_ followed by 0xDC00-0xDFFF 0175 0176 for (var charcode = 0; charcode < 0xDC00; charcode += resolution) { 0177 if (checkEncodeException(encodeFunction,0xD800,charcode)) 0178 passes++; 0179 else 0180 failures++; 0181 } 0182 0183 for (var charcode = 0xE000; charcode <= 0xFFFF; charcode += resolution) { 0184 if (checkEncodeException(encodeFunction,0xD800,charcode)) 0185 passes++; 0186 else 0187 failures++; 0188 } 0189 0190 debug("Unfinished surrogate pairs test (expected exception), passes:" + passes + ", failures:" + failures); 0191 totalFailures += failures; 0192 failures = 0; 0193 passes = 0; 0194 0195 // print("passes = "+passes); 0196 // print("failures = "+failures); 0197 0198 return (totalFailures == 0); 0199 } 0200 0201 0202 shouldBe("checkWithFunctions(encodeURI,decodeURI)","true"); 0203 shouldBe("checkWithFunctions(encodeURIComponent,decodeURIComponent)","true"); 0204 0205 *********** end of disabled tests *********/ 0206 0207 // reserved characters are not supposed to be decoded 0208 shouldBe('decodeURI("%23")', '"%23"'); // # 0209 shouldBe('decodeURI("%24")', '"%24"'); // $ 0210 shouldBe('decodeURI("%26")', '"%26"'); // & 0211 shouldBe('decodeURI("%2b")', '"%2b"'); // + 0212 shouldBe('decodeURI("%2c")', '"%2c"'); // , 0213 shouldBe('decodeURI("%2f")', '"%2f"'); // / 0214 shouldBe('decodeURI("%3a")', '"%3a"'); // : 0215 shouldBe('decodeURI("%3b")', '"%3b"'); // ; 0216 shouldBe('decodeURI("%3d")', '"%3d"'); // = 0217 shouldBe('decodeURI("%3f")', '"%3f"'); // ? 0218 shouldBe('decodeURI("%40")', '"%40"'); // @ 0219 0220 function checkInvalid(s) 0221 { 0222 var d; 0223 try { 0224 d = decodeURI(s); 0225 } catch(e) { 0226 testPassed('decodeURI("' + s + '") threw an exception'); 0227 return; 0228 } 0229 if (d.length == 1 && d.charCodeAt(0) == 65533 || 0230 (d.length == 2 && 0231 d.charCodeAt(0) == 65533 && d.charCodeAt(1) == 65533)) { 0232 testPassed('decodeURI("' + s + '") resulted in replacement chars'); 0233 return; 0234 } 0235 if (d == s) { 0236 testPassed('decodeURI("' + s + '") was not decoded'); 0237 return; 0238 } 0239 0240 testFailed('decodeURI("' + s + '") was decoded to "' + d + '"'); 0241 } 0242 0243 // 0244 // based on http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt 0245 // 0246 0247 // unexpected continuation bytes 0248 checkInvalid("%80"); 0249 checkInvalid("%bf"); 0250 checkInvalid("%80%bf"); 0251 checkInvalid("%80%bf%80"); 0252 checkInvalid("%80%bf%80%bf"); 0253 checkInvalid("%80%bf%80%bf%80"); 0254 checkInvalid("%80%bf%80%bf%80%bf"); 0255 for (var cb = parseInt("80", 16); cb <= parseInt("BF", 16); ++cb) 0256 checkInvalid("%" + cb.toString(16)); 0257 0258 // Lonely start characters 0259 // All 32 first bytes of 2-byte sequences (0xc0-0xdf), 0260 // each followed by a space character 0261 for (var cb = parseInt("C0", 16); cb <= parseInt("DF", 16); ++cb) 0262 checkInvalid("%" + cb.toString(16) + "%20"); 0263 0264 // All 16 first bytes of 3-byte sequences (0xe0-0xef), 0265 // each followed by a space character 0266 for (var cb = parseInt("E0", 16); cb <= parseInt("EF", 16); ++cb) 0267 checkInvalid("%" + cb.toString(16) + "%20"); 0268 0269 // All 8 first bytes of 4-byte sequences (0xf0-0xf7), 0270 // each followed by a space character 0271 for (var cb = parseInt("E0", 16); cb <= parseInt("EF", 16); ++cb) 0272 checkInvalid("%" + cb.toString(16) + "%20"); 0273 0274 // All 4 first bytes of 5-byte sequences (0xf8-0xfb), 0275 // each followed by a space character 0276 for (var cb = parseInt("F8", 16); cb <= parseInt("FB", 16); ++cb) 0277 checkInvalid("%" + cb.toString(16) + "%20"); 0278 0279 // All 2 first bytes of 6-byte sequences (0xfc-0xfd), 0280 // each followed by a space character 0281 for (var cb = parseInt("FC", 16); cb <= parseInt("FD", 16); ++cb) 0282 checkInvalid("%" + cb.toString(16) + "%20"); 0283 0284 // Sequences with last continuation byte missing 0285 checkInvalid("%C0"); // 2-byte sequence with last byte missing (U+0000) 0286 checkInvalid("%E0%80"); // 3-byte sequence with last byte missing (U+0000) 0287 checkInvalid("%F0%80%80"); // 4-byte sequence with last byte missing (U+0000) 0288 checkInvalid("%F8%80%80%80"); 0289 checkInvalid("%FC%80%80%80%80"); 0290 checkInvalid("%DF"); 0291 checkInvalid("%EF%BF"); 0292 checkInvalid("%F7%BF%BF"); 0293 checkInvalid("%FB%BF%BF%BF"); 0294 checkInvalid("%FD%BF%BF%BF%BF"); 0295 0296 // impossible bytes 0297 checkInvalid("%fe"); 0298 checkInvalid("%ff"); 0299 checkInvalid("%fe%fe%ff%ff"); 0300 0301 // overlong ASCII character 0302 checkInvalid("%C0%AF"); 0303 checkInvalid("%E0%80%AF"); 0304 checkInvalid("%F0%80%80%AF"); 0305 checkInvalid("%F8%80%80%80%AF"); 0306 checkInvalid("%FC%80%80%80%80%AF"); 0307 0308 // maximum overlong sequences 0309 checkInvalid("%c1%bf"); 0310 checkInvalid("%e0%9f%bf"); 0311 checkInvalid("%f0%8f%bf%bf"); 0312 checkInvalid("%f8%87%bf%bf%bf"); 0313 checkInvalid("%fc%83%bf%bf%bf%bf"); 0314 0315 checkInvalid("%c0%80"); 0316 checkInvalid("%e0%80%80"); 0317 checkInvalid("%f0%80%80%80"); 0318 checkInvalid("%f8%80%80%80%80"); 0319 checkInvalid("%fc%80%80%80%80%80"); 0320 0321 // invalid single UTF-16 surrogates 0322 checkInvalid("%ed%a0%80"); // U+D800 0323 checkInvalid("%ed%ad%bf"); // U+DB7F 0324 checkInvalid("%ed%ae%80"); // U+DB80 0325 checkInvalid("%ed%af%bf"); // U+DBFF 0326 checkInvalid("%ed%b0%80"); // U+DC00 0327 checkInvalid("%ed%be%80"); // U+DF80 0328 checkInvalid("%ed%bf%bf"); // U+DFFF 0329 0330 // invalid paired UTF-16 surrogates 0331 checkInvalid("%ed%a0%80%ed%b0%80"); // U+D800 U+DC00 0332 checkInvalid("%ed%a0%80%ed%bf%bf"); // U+D800 U+DFFF 0333 checkInvalid("%ed%ad%bf%ed%b0%80"); // U+DB7F U+DC00 0334 checkInvalid("%ed%ad%bf%ed%bf%bf"); // U+DB7F U+DFFF 0335 checkInvalid("%ed%ae%80%ed%b0%80"); // U+DB80 U+DC00 0336 checkInvalid("%ed%ae%80%ed%bf%bf"); // U+DB80 U+DFFF 0337 checkInvalid("%ed%af%bf%ed%b0%80"); // U+DBFF U+DC00 0338 checkInvalid("%ed%af%bf%ed%bf%bf"); // U+DBFF U+DFFF 0339 0340 // Other illegal code positions 0341 checkInvalid("%EF%BF%BE"); // U+FFFE 0342 checkInvalid("%EF%BF%BF"); // U+FFFF 0343 0344 0345 // Regression test, #150381 -- make sure we don't 0346 // reject OK things as invalid. 0347 shouldBe('decodeURIComponent("%C3%A1")', '"\u00e1"'); 0348 0349 0350 debug("Done");