Issue #1480 - improving canonicalPath test cases
This commit is contained in:
parent
ad2fe27303
commit
f64b0409ff
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.util;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class URIUtilCanonicalPathTest
|
||||
{
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static List<String[]> data()
|
||||
{
|
||||
String[][] canonical =
|
||||
{
|
||||
// Basic examples (no changes expected)
|
||||
{"/hello.html", "/hello.html"},
|
||||
{"/css/main.css", "/css/main.css"},
|
||||
{"/", "/"},
|
||||
{"", ""},
|
||||
{"/aaa/bbb/", "/aaa/bbb/"},
|
||||
{"/aaa/bbb", "/aaa/bbb"},
|
||||
{"aaa/bbb", "aaa/bbb"},
|
||||
{"aaa/", "aaa/"},
|
||||
{"aaa", "aaa"},
|
||||
{"a", "a"},
|
||||
{"a/", "a/"},
|
||||
|
||||
// Extra slashes
|
||||
{"/aaa//bbb/", "/aaa//bbb/"},
|
||||
{"/aaa//bbb", "/aaa//bbb"},
|
||||
{"/aaa///bbb/", "/aaa///bbb/"},
|
||||
|
||||
// Path traversal with current references "./"
|
||||
{"/aaa/./bbb/", "/aaa/bbb/"},
|
||||
{"/aaa/./bbb", "/aaa/bbb"},
|
||||
{"./bbb/", "bbb/"},
|
||||
{"./aaa/../bbb/", "bbb/"},
|
||||
{"/foo/.", "/foo/"},
|
||||
{"./", ""},
|
||||
{".", ""},
|
||||
{".//", "/"},
|
||||
{".///", "//"},
|
||||
{"/.", "/"},
|
||||
{"//.", "//"},
|
||||
{"///.", "///"},
|
||||
|
||||
// Path traversal directory (but not past root)
|
||||
{"/aaa/../bbb/", "/bbb/"},
|
||||
{"/aaa/../bbb", "/bbb"},
|
||||
{"/aaa..bbb/", "/aaa..bbb/"},
|
||||
{"/aaa..bbb", "/aaa..bbb"},
|
||||
{"/aaa/..bbb/", "/aaa/..bbb/"},
|
||||
{"/aaa/..bbb", "/aaa/..bbb"},
|
||||
{"/aaa/./../bbb/", "/bbb/"},
|
||||
{"/aaa/./../bbb", "/bbb"},
|
||||
{"/aaa/bbb/ccc/../../ddd/", "/aaa/ddd/"},
|
||||
{"/aaa/bbb/ccc/../../ddd", "/aaa/ddd"},
|
||||
{"/foo/../bar//", "/bar//"},
|
||||
{"/ctx/../bar/../ctx/all/index.txt", "/ctx/all/index.txt"},
|
||||
{"/down/.././index.html", "/index.html"},
|
||||
|
||||
// Path traversal up past root
|
||||
{"..", null},
|
||||
{"./..", null},
|
||||
{"aaa/../..", null},
|
||||
{"/foo/bar/../../..", null},
|
||||
{"/../foo", null},
|
||||
{"a/.", "a/"},
|
||||
{"a/..", ""},
|
||||
{"a/../..", null},
|
||||
{"/foo/../../bar", null},
|
||||
|
||||
// Query parameter specifics
|
||||
{"/ctx/dir?/../index.html", "/ctx/dir?/../index.html"},
|
||||
{"/get-files?file=/etc/passwd", "/get-files?file=/etc/passwd"},
|
||||
{"/get-files?file=../../../../../passwd", "/get-files?file=../../../../../passwd"},
|
||||
|
||||
// Known windows shell quirks
|
||||
{"file.txt ", "file.txt "}, // with spaces
|
||||
{"file.txt...", "file.txt..."}, // extra dots ignored by windows
|
||||
{"file.txt\u0000", "file.txt\u0000"}, // null terminated is ignored by windows
|
||||
{"file.txt\"\"\"\"", "file.txt\"\"\"\""}, // extra quotes ignored by windows
|
||||
{"file.txt<<<>>><", "file.txt<<<>>><"}, // angle brackets at end of path ignored by windows
|
||||
{"././././././file.txt", "file.txt"},
|
||||
|
||||
// Oddball requests that look like path traversal, but are not
|
||||
{"/....", "/...."},
|
||||
{"/..../ctx/..../blah/logo.jpg", "/..../ctx/..../blah/logo.jpg"},
|
||||
|
||||
// paths with encoded segments should remain encoded
|
||||
// canonicalPath() is not responsible for decoding characters
|
||||
{"%2e%2e/", "%2e%2e/"},
|
||||
};
|
||||
return Arrays.asList(canonical);
|
||||
}
|
||||
|
||||
@Parameterized.Parameter(0)
|
||||
public String input;
|
||||
|
||||
@Parameterized.Parameter(1)
|
||||
public String expectedResult;
|
||||
|
||||
@Test
|
||||
public void testCanonicalPath()
|
||||
{
|
||||
assertThat("Canonical", URIUtil.canonicalPath(input), is(expectedResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanonicalPathWithQuery()
|
||||
{
|
||||
// Skip this variation if the actual test contains a query already
|
||||
assumeFalse(input.contains("?"));
|
||||
|
||||
if (expectedResult == null)
|
||||
{
|
||||
assertThat("Canonical with Query", URIUtil.canonicalPath(input + "?a=1"), nullValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
assertThat("Canonical", URIUtil.canonicalPath(input + "?a=1"), is(expectedResult + "?a=1"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,8 +27,6 @@ import static org.junit.Assert.assertTrue;
|
|||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
|
@ -228,78 +226,6 @@ public class URIUtilTest
|
|||
assertFalse(URIUtil.equalsIgnoreEncodings("/foo2fbar","/foo/bar"));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Test
|
||||
public void testCanonicalPath()
|
||||
{
|
||||
String[][] canonical =
|
||||
{
|
||||
{"/aaa/bbb/","/aaa/bbb/"},
|
||||
{"/aaa//bbb/","/aaa//bbb/"},
|
||||
{"/aaa///bbb/","/aaa///bbb/"},
|
||||
{"/aaa/./bbb/","/aaa/bbb/"},
|
||||
{"/aaa/../bbb/","/bbb/"},
|
||||
{"/aaa..bbb/","/aaa..bbb/"},
|
||||
{"/aaa/..bbb/","/aaa/..bbb/"},
|
||||
{"/aaa/./../bbb/","/bbb/"},
|
||||
{"/aaa/bbb/ccc/../../ddd/","/aaa/ddd/"},
|
||||
{"./bbb/","bbb/"},
|
||||
{"./aaa/../bbb/","bbb/"},
|
||||
{"./",""},
|
||||
{".//","/"},
|
||||
{".///","//"},
|
||||
{"/.","/"},
|
||||
{"//.","//"},
|
||||
{"///.","///"},
|
||||
{"/","/"},
|
||||
{"aaa/bbb","aaa/bbb"},
|
||||
{"aaa/","aaa/"},
|
||||
{"aaa","aaa"},
|
||||
{"/aaa/bbb","/aaa/bbb"},
|
||||
{"/aaa//bbb","/aaa//bbb"},
|
||||
{"/aaa/./bbb","/aaa/bbb"},
|
||||
{"/aaa/../bbb","/bbb"},
|
||||
{"/aaa/./../bbb","/bbb"},
|
||||
{"./bbb","bbb"},
|
||||
{"./aaa/../bbb","bbb"},
|
||||
{"aaa/bbb/..","aaa/"},
|
||||
{"aaa/bbb/../","aaa/"},
|
||||
{"/aaa//../bbb","/aaa/bbb"},
|
||||
{"/aaa/./../bbb","/bbb"},
|
||||
{"./",""},
|
||||
{".",""},
|
||||
{"",""},
|
||||
{"..",null},
|
||||
{"./..",null},
|
||||
{"aaa/../..",null},
|
||||
{"/foo/bar/../../..",null},
|
||||
{"/../foo",null},
|
||||
{"/foo/.","/foo/"},
|
||||
{"a","a"},
|
||||
{"a/","a/"},
|
||||
{"a/.","a/"},
|
||||
{"a/..",""},
|
||||
{"a/../..",null},
|
||||
{"/foo/../../bar",null},
|
||||
{"/foo/../bar//","/bar//"},
|
||||
{"/....","/...."},
|
||||
};
|
||||
|
||||
for (int t=0;t<canonical.length;t++)
|
||||
{
|
||||
assertEquals( "canonical "+canonical[t][0],
|
||||
canonical[t][1],
|
||||
URIUtil.canonicalPath(canonical[t][0])
|
||||
);
|
||||
assertEquals( "canonical "+canonical[t][0]+"?a=1",
|
||||
canonical[t][1]==null?null:(canonical[t][1]+"?a=1"),
|
||||
URIUtil.canonicalPath(canonical[t][0]+"?a=1")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Test
|
||||
public void testJarSource() throws Exception
|
||||
|
|
Loading…
Reference in New Issue