1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/test/unit/test_duplicate_headers.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,603 @@ 1.4 +/* 1.5 + * Tests bugs 597706, 655389: prevent duplicate headers with differing values 1.6 + * for some headers like Content-Length, Location, etc. 1.7 + */ 1.8 + 1.9 +//////////////////////////////////////////////////////////////////////////////// 1.10 +// Test infrastructure 1.11 + 1.12 +Cu.import("resource://testing-common/httpd.js"); 1.13 + 1.14 +XPCOMUtils.defineLazyGetter(this, "URL", function() { 1.15 + return "http://localhost:" + httpserver.identity.primaryPort; 1.16 +}); 1.17 + 1.18 +var httpserver = new HttpServer(); 1.19 +var index = 0; 1.20 +var test_flags = new Array(); 1.21 +var testPathBase = "/dupe_hdrs"; 1.22 + 1.23 +function run_test() 1.24 +{ 1.25 + httpserver.start(-1); 1.26 + 1.27 + do_test_pending(); 1.28 + run_test_number(1); 1.29 +} 1.30 + 1.31 +function run_test_number(num) 1.32 +{ 1.33 + testPath = testPathBase + num; 1.34 + httpserver.registerPathHandler(testPath, eval("handler" + num)); 1.35 + 1.36 + var channel = setupChannel(testPath); 1.37 + flags = test_flags[num]; // OK if flags undefined for test 1.38 + channel.asyncOpen(new ChannelListener(eval("completeTest" + num), 1.39 + channel, flags), null); 1.40 +} 1.41 + 1.42 +function setupChannel(url) 1.43 +{ 1.44 + var ios = Components.classes["@mozilla.org/network/io-service;1"]. 1.45 + getService(Ci.nsIIOService); 1.46 + var chan = ios.newChannel(URL + url, "", null); 1.47 + var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel); 1.48 + return httpChan; 1.49 +} 1.50 + 1.51 +function endTests() 1.52 +{ 1.53 + httpserver.stop(do_test_finished); 1.54 +} 1.55 + 1.56 +//////////////////////////////////////////////////////////////////////////////// 1.57 +// Test 1: FAIL because of conflicting Content-Length headers 1.58 +test_flags[1] = CL_EXPECT_FAILURE; 1.59 + 1.60 +function handler1(metadata, response) 1.61 +{ 1.62 + var body = "012345678901234567890123456789"; 1.63 + // Comrades! We must seize power from the petty-bourgeois running dogs of 1.64 + // httpd.js in order to reply with multiple instances of the same header! 1.65 + response.seizePower(); 1.66 + response.write("HTTP/1.0 200 OK\r\n"); 1.67 + response.write("Content-Type: text/plain\r\n"); 1.68 + response.write("Content-Length: 30\r\n"); 1.69 + response.write("Content-Length: 20\r\n"); 1.70 + response.write("\r\n"); 1.71 + response.write(body); 1.72 + response.finish(); 1.73 +} 1.74 + 1.75 + 1.76 +function completeTest1(request, data, ctx) 1.77 +{ 1.78 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.79 + 1.80 + run_test_number(2); 1.81 +} 1.82 + 1.83 +//////////////////////////////////////////////////////////////////////////////// 1.84 +// Test 2: OK to have duplicate same Content-Length headers 1.85 + 1.86 +function handler2(metadata, response) 1.87 +{ 1.88 + var body = "012345678901234567890123456789"; 1.89 + response.seizePower(); 1.90 + response.write("HTTP/1.0 200 OK\r\n"); 1.91 + response.write("Content-Type: text/plain\r\n"); 1.92 + response.write("Content-Length: 30\r\n"); 1.93 + response.write("Content-Length: 30\r\n"); 1.94 + response.write("\r\n"); 1.95 + response.write(body); 1.96 + response.finish(); 1.97 +} 1.98 + 1.99 +function completeTest2(request, data, ctx) 1.100 +{ 1.101 + do_check_eq(request.status, 0); 1.102 + run_test_number(3); 1.103 +} 1.104 + 1.105 +//////////////////////////////////////////////////////////////////////////////// 1.106 +// Test 3: FAIL: 2nd Content-length is blank 1.107 +test_flags[3] = CL_EXPECT_FAILURE; 1.108 + 1.109 +function handler3(metadata, response) 1.110 +{ 1.111 + var body = "012345678901234567890123456789"; 1.112 + response.seizePower(); 1.113 + response.write("HTTP/1.0 200 OK\r\n"); 1.114 + response.write("Content-Type: text/plain\r\n"); 1.115 + response.write("Content-Length: 30\r\n"); 1.116 + response.write("Content-Length:\r\n"); 1.117 + response.write("\r\n"); 1.118 + response.write(body); 1.119 + response.finish(); 1.120 +} 1.121 + 1.122 +function completeTest3(request, data, ctx) 1.123 +{ 1.124 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.125 + 1.126 + run_test_number(4); 1.127 +} 1.128 + 1.129 +//////////////////////////////////////////////////////////////////////////////// 1.130 +// Test 4: ensure that blank C-len header doesn't allow attacker to reset Clen, 1.131 +// then insert CRLF attack 1.132 +test_flags[4] = CL_EXPECT_FAILURE; 1.133 + 1.134 +function handler4(metadata, response) 1.135 +{ 1.136 + var body = "012345678901234567890123456789"; 1.137 + 1.138 + response.seizePower(); 1.139 + response.write("HTTP/1.0 200 OK\r\n"); 1.140 + response.write("Content-Type: text/plain\r\n"); 1.141 + response.write("Content-Length: 30\r\n"); 1.142 + 1.143 + // Bad Mr Hacker! Bad! 1.144 + var evilBody = "We are the Evil bytes, Evil bytes, Evil bytes!"; 1.145 + response.write("Content-Length:\r\n"); 1.146 + response.write("Content-Length: %s\r\n\r\n%s" % (evilBody.length, evilBody)); 1.147 + response.write("\r\n"); 1.148 + response.write(body); 1.149 + response.finish(); 1.150 +} 1.151 + 1.152 +function completeTest4(request, data, ctx) 1.153 +{ 1.154 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.155 + 1.156 + run_test_number(5); 1.157 +} 1.158 + 1.159 + 1.160 +//////////////////////////////////////////////////////////////////////////////// 1.161 +// Test 5: ensure that we take 1st instance of duplicate, nonmerged headers that 1.162 +// are permitted : (ex: Referrer) 1.163 + 1.164 +function handler5(metadata, response) 1.165 +{ 1.166 + var body = "012345678901234567890123456789"; 1.167 + response.seizePower(); 1.168 + response.write("HTTP/1.0 200 OK\r\n"); 1.169 + response.write("Content-Type: text/plain\r\n"); 1.170 + response.write("Content-Length: 30\r\n"); 1.171 + response.write("Referer: naive.org\r\n"); 1.172 + response.write("Referer: evil.net\r\n"); 1.173 + response.write("\r\n"); 1.174 + response.write(body); 1.175 + response.finish(); 1.176 +} 1.177 + 1.178 +function completeTest5(request, data, ctx) 1.179 +{ 1.180 + try { 1.181 + referer = request.getResponseHeader("Referer"); 1.182 + do_check_eq(referer, "naive.org"); 1.183 + } catch (ex) { 1.184 + do_throw("Referer header should be present"); 1.185 + } 1.186 + 1.187 + run_test_number(6); 1.188 +} 1.189 + 1.190 +//////////////////////////////////////////////////////////////////////////////// 1.191 +// Test 5: FAIL if multiple, different Location: headers present 1.192 +// - needed to prevent CRLF injection attacks 1.193 +test_flags[6] = CL_EXPECT_FAILURE; 1.194 + 1.195 +function handler6(metadata, response) 1.196 +{ 1.197 + var body = "012345678901234567890123456789"; 1.198 + response.seizePower(); 1.199 + response.write("HTTP/1.0 301 Moved\r\n"); 1.200 + response.write("Content-Type: text/plain\r\n"); 1.201 + response.write("Content-Length: 30\r\n"); 1.202 + response.write("Location: " + URL + "/content\r\n"); 1.203 + response.write("Location: http://www.microsoft.com/\r\n"); 1.204 + response.write("Connection: close\r\n"); 1.205 + response.write("\r\n"); 1.206 + response.write(body); 1.207 + response.finish(); 1.208 +} 1.209 + 1.210 +function completeTest6(request, data, ctx) 1.211 +{ 1.212 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.213 + 1.214 +// run_test_number(7); // Test 7 leaking under e10s: unrelated bug? 1.215 + run_test_number(8); 1.216 +} 1.217 + 1.218 +//////////////////////////////////////////////////////////////////////////////// 1.219 +// Test 7: OK to have multiple Location: headers with same value 1.220 + 1.221 +function handler7(metadata, response) 1.222 +{ 1.223 + var body = "012345678901234567890123456789"; 1.224 + response.seizePower(); 1.225 + response.write("HTTP/1.0 301 Moved\r\n"); 1.226 + response.write("Content-Type: text/plain\r\n"); 1.227 + response.write("Content-Length: 30\r\n"); 1.228 + // redirect to previous test handler that completes OK: test 5 1.229 + response.write("Location: " + URL + testPathBase + "5\r\n"); 1.230 + response.write("Location: " + URL + testPathBase + "5\r\n"); 1.231 + response.write("Connection: close\r\n"); 1.232 + response.write("\r\n"); 1.233 + response.write(body); 1.234 + response.finish(); 1.235 +} 1.236 + 1.237 +function completeTest7(request, data, ctx) 1.238 +{ 1.239 + // for some reason need this here 1.240 + request.QueryInterface(Components.interfaces.nsIHttpChannel); 1.241 + 1.242 + try { 1.243 + referer = request.getResponseHeader("Referer"); 1.244 + do_check_eq(referer, "naive.org"); 1.245 + } catch (ex) { 1.246 + do_throw("Referer header should be present"); 1.247 + } 1.248 + 1.249 + run_test_number(8); 1.250 +} 1.251 + 1.252 +//////////////////////////////////////////////////////////////////////////////// 1.253 +// FAIL if 2nd Location: headers blank 1.254 +test_flags[8] = CL_EXPECT_FAILURE; 1.255 + 1.256 +function handler8(metadata, response) 1.257 +{ 1.258 + var body = "012345678901234567890123456789"; 1.259 + response.seizePower(); 1.260 + response.write("HTTP/1.0 301 Moved\r\n"); 1.261 + response.write("Content-Type: text/plain\r\n"); 1.262 + response.write("Content-Length: 30\r\n"); 1.263 + // redirect to previous test handler that completes OK: test 4 1.264 + response.write("Location: " + URL + testPathBase + "4\r\n"); 1.265 + response.write("Location:\r\n"); 1.266 + response.write("Connection: close\r\n"); 1.267 + response.write("\r\n"); 1.268 + response.write(body); 1.269 + response.finish(); 1.270 +} 1.271 + 1.272 +function completeTest8(request, data, ctx) 1.273 +{ 1.274 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.275 + 1.276 + run_test_number(9); 1.277 +} 1.278 + 1.279 +//////////////////////////////////////////////////////////////////////////////// 1.280 +// Test 9: ensure that blank Location header doesn't allow attacker to reset, 1.281 +// then insert an evil one 1.282 +test_flags[9] = CL_EXPECT_FAILURE; 1.283 + 1.284 +function handler9(metadata, response) 1.285 +{ 1.286 + var body = "012345678901234567890123456789"; 1.287 + response.seizePower(); 1.288 + response.write("HTTP/1.0 301 Moved\r\n"); 1.289 + response.write("Content-Type: text/plain\r\n"); 1.290 + response.write("Content-Length: 30\r\n"); 1.291 + // redirect to previous test handler that completes OK: test 2 1.292 + response.write("Location: " + URL + testPathBase + "2\r\n"); 1.293 + response.write("Location:\r\n"); 1.294 + // redirect to previous test handler that completes OK: test 4 1.295 + response.write("Location: " + URL + testPathBase + "4\r\n"); 1.296 + response.write("Connection: close\r\n"); 1.297 + response.write("\r\n"); 1.298 + response.write(body); 1.299 + response.finish(); 1.300 +} 1.301 + 1.302 +function completeTest9(request, data, ctx) 1.303 +{ 1.304 + // All redirection should fail: 1.305 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.306 + 1.307 + run_test_number(10); 1.308 +} 1.309 + 1.310 +//////////////////////////////////////////////////////////////////////////////// 1.311 +// Test 10: FAIL: if conflicting values for Content-Dispo 1.312 +test_flags[10] = CL_EXPECT_FAILURE; 1.313 + 1.314 +function handler10(metadata, response) 1.315 +{ 1.316 + var body = "012345678901234567890123456789"; 1.317 + response.seizePower(); 1.318 + response.write("HTTP/1.0 200 OK\r\n"); 1.319 + response.write("Content-Type: text/plain\r\n"); 1.320 + response.write("Content-Length: 30\r\n"); 1.321 + response.write("Content-Disposition: attachment; filename=foo\r\n"); 1.322 + response.write("Content-Disposition: attachment; filename=bar\r\n"); 1.323 + response.write("Content-Disposition: attachment; filename=baz\r\n"); 1.324 + response.write("\r\n"); 1.325 + response.write(body); 1.326 + response.finish(); 1.327 +} 1.328 + 1.329 + 1.330 +function completeTest10(request, data, ctx) 1.331 +{ 1.332 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.333 + 1.334 + run_test_number(11); 1.335 +} 1.336 + 1.337 +//////////////////////////////////////////////////////////////////////////////// 1.338 +// Test 11: OK to have duplicate same Content-Disposition headers 1.339 + 1.340 +function handler11(metadata, response) 1.341 +{ 1.342 + var body = "012345678901234567890123456789"; 1.343 + response.seizePower(); 1.344 + response.write("HTTP/1.0 200 OK\r\n"); 1.345 + response.write("Content-Type: text/plain\r\n"); 1.346 + response.write("Content-Length: 30\r\n"); 1.347 + response.write("Content-Disposition: attachment; filename=foo\r\n"); 1.348 + response.write("Content-Disposition: attachment; filename=foo\r\n"); 1.349 + response.write("\r\n"); 1.350 + response.write(body); 1.351 + response.finish(); 1.352 +} 1.353 + 1.354 +function completeTest11(request, data, ctx) 1.355 +{ 1.356 + do_check_eq(request.status, 0); 1.357 + 1.358 + try { 1.359 + var chan = request.QueryInterface(Ci.nsIChannel); 1.360 + do_check_eq(chan.contentDisposition, chan.DISPOSITION_ATTACHMENT); 1.361 + do_check_eq(chan.contentDispositionFilename, "foo"); 1.362 + do_check_eq(chan.contentDispositionHeader, "attachment; filename=foo"); 1.363 + } catch (ex) { 1.364 + do_throw("error parsing Content-Disposition: " + ex); 1.365 + } 1.366 + 1.367 + run_test_number(12); 1.368 +} 1.369 + 1.370 +//////////////////////////////////////////////////////////////////////////////// 1.371 +// Bug 716801 OK for Location: header to be blank 1.372 + 1.373 +function handler12(metadata, response) 1.374 +{ 1.375 + var body = "012345678901234567890123456789"; 1.376 + response.seizePower(); 1.377 + response.write("HTTP/1.0 200 OK\r\n"); 1.378 + response.write("Content-Type: text/plain\r\n"); 1.379 + response.write("Content-Length: 30\r\n"); 1.380 + response.write("Location:\r\n"); 1.381 + response.write("Connection: close\r\n"); 1.382 + response.write("\r\n"); 1.383 + response.write(body); 1.384 + response.finish(); 1.385 +} 1.386 + 1.387 +function completeTest12(request, data, ctx) 1.388 +{ 1.389 + do_check_eq(request.status, Components.results.NS_OK); 1.390 + do_check_eq(30, data.length); 1.391 + 1.392 + run_test_number(13); 1.393 +} 1.394 + 1.395 +//////////////////////////////////////////////////////////////////////////////// 1.396 +// Negative content length is ok 1.397 +test_flags[13] = CL_ALLOW_UNKNOWN_CL; 1.398 + 1.399 +function handler13(metadata, response) 1.400 +{ 1.401 + var body = "012345678901234567890123456789"; 1.402 + response.seizePower(); 1.403 + response.write("HTTP/1.0 200 OK\r\n"); 1.404 + response.write("Content-Type: text/plain\r\n"); 1.405 + response.write("Content-Length: -1\r\n"); 1.406 + response.write("Connection: close\r\n"); 1.407 + response.write("\r\n"); 1.408 + response.write(body); 1.409 + response.finish(); 1.410 +} 1.411 + 1.412 +function completeTest13(request, data, ctx) 1.413 +{ 1.414 + do_check_eq(request.status, Components.results.NS_OK); 1.415 + do_check_eq(30, data.length); 1.416 + 1.417 + run_test_number(14); 1.418 +} 1.419 + 1.420 +//////////////////////////////////////////////////////////////////////////////// 1.421 +// leading negative content length is not ok if paired with positive one 1.422 + 1.423 +test_flags[14] = CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL; 1.424 + 1.425 +function handler14(metadata, response) 1.426 +{ 1.427 + var body = "012345678901234567890123456789"; 1.428 + response.seizePower(); 1.429 + response.write("HTTP/1.0 200 OK\r\n"); 1.430 + response.write("Content-Type: text/plain\r\n"); 1.431 + response.write("Content-Length: -1\r\n"); 1.432 + response.write("Content-Length: 30\r\n"); 1.433 + response.write("Connection: close\r\n"); 1.434 + response.write("\r\n"); 1.435 + response.write(body); 1.436 + response.finish(); 1.437 +} 1.438 + 1.439 +function completeTest14(request, data, ctx) 1.440 +{ 1.441 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.442 + 1.443 + run_test_number(15); 1.444 +} 1.445 + 1.446 +//////////////////////////////////////////////////////////////////////////////// 1.447 +// trailing negative content length is not ok if paired with positive one 1.448 + 1.449 +test_flags[15] = CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL; 1.450 + 1.451 +function handler15(metadata, response) 1.452 +{ 1.453 + var body = "012345678901234567890123456789"; 1.454 + response.seizePower(); 1.455 + response.write("HTTP/1.0 200 OK\r\n"); 1.456 + response.write("Content-Type: text/plain\r\n"); 1.457 + response.write("Content-Length: 30\r\n"); 1.458 + response.write("Content-Length: -1\r\n"); 1.459 + response.write("Connection: close\r\n"); 1.460 + response.write("\r\n"); 1.461 + response.write(body); 1.462 + response.finish(); 1.463 +} 1.464 + 1.465 +function completeTest15(request, data, ctx) 1.466 +{ 1.467 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.468 + 1.469 + run_test_number(16); 1.470 +} 1.471 + 1.472 +//////////////////////////////////////////////////////////////////////////////// 1.473 +// empty content length is ok 1.474 +test_flags[16] = CL_ALLOW_UNKNOWN_CL; 1.475 +reran16 = false; 1.476 + 1.477 +function handler16(metadata, response) 1.478 +{ 1.479 + var body = "012345678901234567890123456789"; 1.480 + response.seizePower(); 1.481 + response.write("HTTP/1.0 200 OK\r\n"); 1.482 + response.write("Content-Type: text/plain\r\n"); 1.483 + response.write("Content-Length: \r\n"); 1.484 + response.write("Cache-Control: max-age=600\r\n"); 1.485 + response.write("Connection: close\r\n"); 1.486 + response.write("\r\n"); 1.487 + response.write(body); 1.488 + response.finish(); 1.489 +} 1.490 + 1.491 +function completeTest16(request, data, ctx) 1.492 +{ 1.493 + do_check_eq(request.status, Components.results.NS_OK); 1.494 + do_check_eq(30, data.length); 1.495 + 1.496 + if (!reran16) { 1.497 + reran16 = true; 1.498 + run_test_number(16); 1.499 + } 1.500 + else { 1.501 + run_test_number(17); 1.502 + } 1.503 +} 1.504 + 1.505 +//////////////////////////////////////////////////////////////////////////////// 1.506 +// empty content length paired with non empty is not ok 1.507 +test_flags[17] = CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL; 1.508 + 1.509 +function handler17(metadata, response) 1.510 +{ 1.511 + var body = "012345678901234567890123456789"; 1.512 + response.seizePower(); 1.513 + response.write("HTTP/1.0 200 OK\r\n"); 1.514 + response.write("Content-Type: text/plain\r\n"); 1.515 + response.write("Content-Length: \r\n"); 1.516 + response.write("Content-Length: 30\r\n"); 1.517 + response.write("Connection: close\r\n"); 1.518 + response.write("\r\n"); 1.519 + response.write(body); 1.520 + response.finish(); 1.521 +} 1.522 + 1.523 +function completeTest17(request, data, ctx) 1.524 +{ 1.525 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.526 + 1.527 + run_test_number(18); 1.528 +} 1.529 + 1.530 +//////////////////////////////////////////////////////////////////////////////// 1.531 +// alpha content-length is just like -1 1.532 +test_flags[18] = CL_ALLOW_UNKNOWN_CL; 1.533 + 1.534 +function handler18(metadata, response) 1.535 +{ 1.536 + var body = "012345678901234567890123456789"; 1.537 + response.seizePower(); 1.538 + response.write("HTTP/1.0 200 OK\r\n"); 1.539 + response.write("Content-Type: text/plain\r\n"); 1.540 + response.write("Content-Length: seventeen\r\n"); 1.541 + response.write("Connection: close\r\n"); 1.542 + response.write("\r\n"); 1.543 + response.write(body); 1.544 + response.finish(); 1.545 +} 1.546 + 1.547 +function completeTest18(request, data, ctx) 1.548 +{ 1.549 + do_check_eq(request.status, Components.results.NS_OK); 1.550 + do_check_eq(30, data.length); 1.551 + 1.552 + run_test_number(19); 1.553 +} 1.554 + 1.555 +//////////////////////////////////////////////////////////////////////////////// 1.556 +// semi-colons are ok too in the content-length 1.557 +test_flags[19] = CL_ALLOW_UNKNOWN_CL; 1.558 + 1.559 +function handler19(metadata, response) 1.560 +{ 1.561 + var body = "012345678901234567890123456789"; 1.562 + response.seizePower(); 1.563 + response.write("HTTP/1.0 200 OK\r\n"); 1.564 + response.write("Content-Type: text/plain\r\n"); 1.565 + response.write("Content-Length: 30;\r\n"); 1.566 + response.write("Connection: close\r\n"); 1.567 + response.write("\r\n"); 1.568 + response.write(body); 1.569 + response.finish(); 1.570 +} 1.571 + 1.572 +function completeTest19(request, data, ctx) 1.573 +{ 1.574 + do_check_eq(request.status, Components.results.NS_OK); 1.575 + do_check_eq(30, data.length); 1.576 + 1.577 + run_test_number(20); 1.578 +} 1.579 + 1.580 +//////////////////////////////////////////////////////////////////////////////// 1.581 +// FAIL if 1st Location: header is blank, followed by non-blank 1.582 +test_flags[20] = CL_EXPECT_FAILURE; 1.583 + 1.584 +function handler20(metadata, response) 1.585 +{ 1.586 + var body = "012345678901234567890123456789"; 1.587 + response.seizePower(); 1.588 + response.write("HTTP/1.0 301 Moved\r\n"); 1.589 + response.write("Content-Type: text/plain\r\n"); 1.590 + response.write("Content-Length: 30\r\n"); 1.591 + // redirect to previous test handler that completes OK: test 4 1.592 + response.write("Location:\r\n"); 1.593 + response.write("Location: " + URL + testPathBase + "4\r\n"); 1.594 + response.write("Connection: close\r\n"); 1.595 + response.write("\r\n"); 1.596 + response.write(body); 1.597 + response.finish(); 1.598 +} 1.599 + 1.600 +function completeTest20(request, data, ctx) 1.601 +{ 1.602 + do_check_eq(request.status, Components.results.NS_ERROR_CORRUPTED_CONTENT); 1.603 + 1.604 + endTests(); 1.605 +} 1.606 +