Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UriCompliance Violation FRAGMENT #12504

Merged
merged 2 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,7 @@ private void parse(State state, final String uri)
case '#':
// must have been in a path
_path = uri.substring(mark, i);
addViolation(Violation.FRAGMENT);
state = State.FRAGMENT;
break;
default:
Expand Down Expand Up @@ -1303,7 +1304,11 @@ private void parse(State state, final String uri)
state = switch (c)
{
case '?' -> State.QUERY;
case '#' -> State.FRAGMENT;
case '#' ->
{
addViolation(Violation.FRAGMENT);
yield State.FRAGMENT;
}
default -> throw new IllegalArgumentException("Bad authority");
};
}
Expand Down Expand Up @@ -1411,7 +1416,11 @@ else if (!isUnreservedPctEncodedOrSubDelim(c))
state = switch (c)
{
case '?' -> State.QUERY;
case '#' -> State.FRAGMENT;
case '#' ->
{
addViolation(Violation.FRAGMENT);
yield State.FRAGMENT;
}
default -> throw new IllegalStateException();
};
}
Expand Down Expand Up @@ -1494,6 +1503,7 @@ else if (!isUnreservedPctEncodedOrSubDelim(c))
checkSegment(uri, dot || encoded, segment, i, false);
_path = uri.substring(pathMark, i);
mark = i + 1;
addViolation(Violation.FRAGMENT);
state = State.FRAGMENT;
break;
case '/':
Expand Down Expand Up @@ -1536,6 +1546,7 @@ else if (!isUnreservedPctEncodedOrSubDelim(c))
_path = uri.substring(pathMark, i);
_param = uri.substring(mark, i);
mark = i + 1;
addViolation(Violation.FRAGMENT);
state = State.FRAGMENT;
break;
case '/':
Expand All @@ -1557,6 +1568,7 @@ else if (!isUnreservedPctEncodedOrSubDelim(c))
{
_query = uri.substring(mark, i);
mark = i + 1;
addViolation(Violation.FRAGMENT);
state = State.FRAGMENT;
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,12 @@ public enum Violation implements ComplianceViolation
/**
* Allow user info in the authority portion of the URI and HTTP specs.
*/
USER_INFO("https://datatracker.ietf.org/doc/html/rfc9110#name-deprecation-of-userinfo-in-", "Deprecated User Info");
USER_INFO("https://datatracker.ietf.org/doc/html/rfc9110#name-deprecation-of-userinfo-in-", "Deprecated User Info"),

/**
* Allow a fragment in the URI.
*/
FRAGMENT("https://www.rfc-editor.org/rfc/rfc9110.html#section-7.1", "Fragment");

private final String _url;
private final String _description;
Expand Down Expand Up @@ -166,7 +171,8 @@ public String getDescription()
Violation.AMBIGUOUS_PATH_SEGMENT,
Violation.AMBIGUOUS_PATH_SEPARATOR,
Violation.SUSPICIOUS_PATH_CHARACTERS,
Violation.ILLEGAL_PATH_CHARACTERS));
Violation.ILLEGAL_PATH_CHARACTERS,
Violation.FRAGMENT));

/**
* Compliance mode that exactly follows <a href="https://tools.ietf.org/html/rfc3986">RFC3986</a>,
Expand Down Expand Up @@ -197,7 +203,8 @@ public String getDescription()
Violation.AMBIGUOUS_PATH_ENCODING,
Violation.AMBIGUOUS_EMPTY_SEGMENT,
Violation.UTF16_ENCODINGS,
Violation.USER_INFO));
Violation.USER_INFO,
Violation.FRAGMENT));

/**
* Compliance mode that allows all URI Violations, including allowing ambiguous paths in non-canonical form, and illegal characters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,9 @@ public static Stream<Arguments> decodePathTests()
{"/context/dir%3B/", "/context/dir%3B/", "/context/dir;/", EnumSet.noneOf(Violation.class)},
{"/f%u006f%u006F/bar", "/foo/bar", "/foo/bar", EnumSet.of(Violation.UTF16_ENCODINGS)},
{"/f%u0001%u0001/bar", "/f%01%01/bar", "/f\001\001/bar", EnumSet.of(Violation.UTF16_ENCODINGS)},
// @checkstyle-disable-check : AvoidEscapedUnicodeCharactersCheck
{"/foo/%u20AC/bar", "/foo/\u20AC/bar", "/foo/\u20AC/bar", EnumSet.of(Violation.UTF16_ENCODINGS)},
// @checkstyle-enable-check : AvoidEscapedUnicodeCharactersCheck

// nfc encoded unicode path
{"/dir/swedish-%C3%A5.txt", "/dir/swedish-å.txt", "/dir/swedish-å.txt", EnumSet.noneOf(Violation.class)},
Expand Down Expand Up @@ -497,6 +499,11 @@ public static Stream<Arguments> decodePathTests()
{"http://localhost:9000/x\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32", "/x\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32", "/x\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32", EnumSet.noneOf(Violation.class)},
{"http://localhost:9000/\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32", "/\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32", "/\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32\uD83C\uDF32", EnumSet.noneOf(Violation.class)},
// @checkstyle-enable-check : AvoidEscapedUnicodeCharactersCheck

// Fragments
{"http://host/path/info#fragment", "/path/info", "/path/info", EnumSet.of(Violation.FRAGMENT)},
{"//host/path/info#frag/ment", "/path/info", "/path/info", EnumSet.of(Violation.FRAGMENT)},
{"/path/info#fragment", "/path/info", "/path/info", EnumSet.of(Violation.FRAGMENT)}
}).map(Arguments::of);
}

Expand All @@ -511,7 +518,7 @@ public void testDecodedPath(String input, String canonicalPath, String decodedPa
assertThat("Decoded Path", uri.getDecodedPath(), is(decodedPath));

EnumSet<Violation> ambiguous = EnumSet.copyOf(expected);
ambiguous.retainAll(EnumSet.complementOf(EnumSet.of(Violation.UTF16_ENCODINGS, Violation.BAD_UTF8_ENCODING)));
ambiguous.retainAll(UriCompliance.AMBIGUOUS_VIOLATIONS);

assertThat(uri.isAmbiguous(), is(!ambiguous.isEmpty()));
assertThat(uri.hasAmbiguousSegment(), is(ambiguous.contains(Violation.AMBIGUOUS_PATH_SEGMENT)));
Expand Down Expand Up @@ -913,9 +920,9 @@ public void testParseString(String input, String scheme, String host, Integer po

@ParameterizedTest
@MethodSource("parseData")
public void testParseURI(String input, String scheme, String host, Integer port, String path, String param, String query, String fragment) throws Exception
public void testParseURI(String input, String scheme, String host, Integer port, String path, String param, String query, String fragment)
{
URI javaUri = null;
URI javaUri;
try
{
javaUri = new URI(input);
Expand All @@ -940,7 +947,7 @@ public void testParseURI(String input, String scheme, String host, Integer port,

@ParameterizedTest
@MethodSource("parseData")
public void testCompareToJavaNetURI(String input, String scheme, String host, Integer port, String path, String param, String query, String fragment) throws Exception
public void testCompareToJavaNetURI(String input, String scheme, String host, Integer port, String path, String param, String query, String fragment)
{
URI javaUri = null;
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.http.UriCompliance;
import org.eclipse.jetty.io.Content;
import org.eclipse.jetty.io.QuietException;
import org.eclipse.jetty.util.BlockingArrayQueue;
Expand Down Expand Up @@ -90,6 +91,7 @@ private void start(String formatString, Handler handler, Consumer<CustomRequestL
{
_server = new Server();
_httpConfig = new HttpConfiguration();
_httpConfig.setUriCompliance(UriCompliance.DEFAULT.with("fragments", UriCompliance.Violation.FRAGMENT));
_serverConnector = new ServerConnector(_server, 1, 1, new HttpConnectionFactory(_httpConfig));
_server.addConnector(_serverConnector);
TestRequestLogWriter writer = new TestRequestLogWriter();
Expand Down Expand Up @@ -165,10 +167,7 @@ public void testRequestFilter() throws Exception
public void testIgnorePaths(String testPath, boolean existsInLog) throws Exception
{
start("RequestPath: %U",
customRequestLog ->
{
customRequestLog.setIgnorePaths(new String[]{"/zed/*", "/zee/*"});
});
customRequestLog -> customRequestLog.setIgnorePaths(new String[]{"/zed/*", "/zee/*"}));

HttpTester.Response response = getResponse("GET @PATH@ HTTP/1.0\n\n".replace("@PATH@", testPath));
assertEquals(HttpStatus.OK_200, response.getStatus());
Expand Down Expand Up @@ -245,8 +244,7 @@ public void testDoublePercent() throws Exception
@Test
public void testLogAddress() throws Exception
{
start("" +
"%{local}a|%{local}p|" +
start("%{local}a|%{local}p|" +
"%{remote}a|%{remote}p|" +
"%{server}a|%{server}p|" +
"%{client}a|%{client}p");
Expand Down Expand Up @@ -337,7 +335,7 @@ public boolean handle(Request request, Response response, Callback callback)
HttpTester.Response response = getResponse("""
GET / HTTP/1.0
Content-Length: %d

%s""".formatted(content.length(), content));
assertEquals(HttpStatus.OK_200, response.getStatus());
String log = _logs.poll(5, TimeUnit.SECONDS);
Expand Down Expand Up @@ -449,9 +447,9 @@ public void testLogKeepAliveRequests() throws Exception

GET /a HTTP/1.1
Host: localhost

GET /a HTTP/1.0

""", 3);

assertThat(_logs.poll(5, TimeUnit.SECONDS), is("KeepAliveRequests: 1"));
Expand Down Expand Up @@ -755,7 +753,7 @@ public boolean handle(Request request, Response response, Callback callback)
output.write("""
GET /abort HTTP/1.1
Host: localhost

""".getBytes(StandardCharsets.ISO_8859_1));
output.flush();

Expand All @@ -764,7 +762,7 @@ public boolean handle(Request request, Response response, Callback callback)

String line = in.readLine();
assertThat(line, is("HTTP/1.1 200 OK"));
while (line != null && line.length() > 0)
while (line != null && !line.isEmpty())
line = in.readLine();

line = in.readLine();
Expand Down
Loading