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");