Issue #1480 - improving canonicalPath test cases

This commit is contained in:
Joakim Erdfelt 2017-04-19 12:16:42 -07:00
parent ad2fe27303
commit f64b0409ff
2 changed files with 150 additions and 74 deletions

View File

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

View File

@ -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