Skip to content

Commit c6ad90c

Browse files
authored
Merge pull request #1411 from rmartinc/UNDERTOW-2206
[UNDERTOW-1591][UNDERTOW-2123][UNDERTOW-2206] IAE trying to decode a requestPath
2 parents d9d891b + bd64ced commit c6ad90c

File tree

14 files changed

+900
-206
lines changed

14 files changed

+900
-206
lines changed

core/src/main/java/io/undertow/server/Connectors.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@
3232
import io.undertow.util.StatusCodes;
3333
import io.undertow.util.URLUtils;
3434
import io.undertow.connector.PooledByteBuffer;
35+
import org.xnio.OptionMap;
3536
import org.xnio.channels.StreamSourceChannel;
3637
import org.xnio.conduits.ConduitStreamSinkChannel;
3738

3839
import java.io.IOException;
40+
import java.nio.charset.StandardCharsets;
3941
import java.util.Date;
4042
import java.util.concurrent.Executor;
4143
import java.util.concurrent.RejectedExecutionException;
@@ -447,13 +449,33 @@ public static void setExchangeRequestPath(final HttpServerExchange exchange, fin
447449
throw new RuntimeException(e);
448450
}
449451
}
450-
/**
451-
* Sets the request path and query parameters, decoding to the requested charset.
452-
*
453-
* @param exchange The exchange
454-
* @param encodedPath The encoded path
455-
* @param charset The charset
456-
*/
452+
453+
/**
454+
* Sets the request path and query parameters, decoding to the requested charset.
455+
* All the options are retrieved from the exchange undertow options.
456+
*
457+
* @param exchange The exchange
458+
* @param encodedPath The encoded path to decode
459+
* @param decodeBuffer The decode buffer to use
460+
* @throws ParameterLimitException
461+
*/
462+
public static void setExchangeRequestPath(final HttpServerExchange exchange, final String encodedPath, StringBuilder decodeBuffer) throws ParameterLimitException {
463+
final OptionMap options = exchange.getConnection().getUndertowOptions();
464+
setExchangeRequestPath(exchange, encodedPath,
465+
options.get(UndertowOptions.URL_CHARSET, StandardCharsets.UTF_8.name()),
466+
options.get(UndertowOptions.DECODE_URL, true),
467+
options.get(UndertowOptions.ALLOW_ENCODED_SLASH, false),
468+
decodeBuffer,
469+
options.get(UndertowOptions.MAX_PARAMETERS, UndertowOptions.DEFAULT_MAX_PARAMETERS));
470+
}
471+
472+
/**
473+
* Sets the request path and query parameters, decoding to the requested charset.
474+
*
475+
* @param exchange The exchange
476+
* @param encodedPath The encoded path
477+
* @param charset The charset
478+
*/
457479
public static void setExchangeRequestPath(final HttpServerExchange exchange, final String encodedPath, final String charset, boolean decode, final boolean allowEncodedSlash, StringBuilder decodeBuffer, int maxParameters) throws ParameterLimitException {
458480
boolean requiresDecode = false;
459481
final StringBuilder pathBuilder = new StringBuilder();

core/src/main/java/io/undertow/server/protocol/http/HttpRequestParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ final void handlePathParameters(ByteBuffer buffer, ParseState state, HttpServerE
619619
handleParsedParam(param, stringBuilder.substring(pos), exchange, urlDecodeRequired, state);
620620
final String path = stringBuilder.toString();
621621
// the canonicalPathStart should be the current length to not add anything to it
622-
parsePathComplete(state, exchange, path.length(), state.parseState, urlDecodeRequired, path);
622+
parsePathComplete(state, exchange, path.length(), state.parseState, state.urlDecodeRequired, path);
623623
state.state = ParseState.VERSION;
624624
state.nextQueryParam = null;
625625
if (next == '?') {

servlet/src/main/java/io/undertow/servlet/spec/AsyncContextImpl.java

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@
2121
import java.io.IOException;
2222
import java.util.ArrayDeque;
2323
import java.util.Deque;
24-
import java.util.HashMap;
2524
import java.util.List;
26-
import java.util.Map;
2725
import java.util.concurrent.CopyOnWriteArrayList;
2826
import java.util.concurrent.Executor;
2927
import java.util.concurrent.TimeUnit;
@@ -61,8 +59,10 @@
6159
import io.undertow.servlet.handlers.ServletDebugPageHandler;
6260
import io.undertow.servlet.handlers.ServletPathMatch;
6361
import io.undertow.servlet.handlers.ServletRequestContext;
62+
import io.undertow.servlet.util.DispatchUtils;
6463
import io.undertow.util.CanonicalPathUtils;
6564
import io.undertow.util.Headers;
65+
import io.undertow.util.ParameterLimitException;
6666
import io.undertow.util.SameThreadExecutor;
6767
import io.undertow.util.StatusCodes;
6868
import io.undertow.util.WorkerUtils;
@@ -219,53 +219,15 @@ public void dispatch(final ServletContext context, final String path) {
219219

220220
HttpServletRequestImpl requestImpl = servletRequestContext.getOriginalRequest();
221221
HttpServletResponseImpl responseImpl = servletRequestContext.getOriginalResponse();
222-
final HttpServerExchange exchange = requestImpl.getExchange();
223222

224-
exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).setDispatcherType(DispatcherType.ASYNC);
225-
226-
requestImpl.setAttribute(ASYNC_REQUEST_URI, requestImpl.getOriginalRequestURI());
227-
requestImpl.setAttribute(ASYNC_CONTEXT_PATH, requestImpl.getOriginalContextPath());
228-
requestImpl.setAttribute(ASYNC_SERVLET_PATH, requestImpl.getOriginalServletPath());
229-
requestImpl.setAttribute(ASYNC_QUERY_STRING, requestImpl.getOriginalQueryString());
230-
231-
String newQueryString = "";
232-
int qsPos = path.indexOf("?");
233-
String newServletPath = path;
234-
if (qsPos != -1) {
235-
newQueryString = newServletPath.substring(qsPos + 1);
236-
newServletPath = newServletPath.substring(0, qsPos);
237-
}
238-
String newRequestUri = context.getContextPath() + newServletPath;
239-
240-
//todo: a more efficient impl
241-
Map<String, Deque<String>> newQueryParameters = new HashMap<>();
242-
for (String part : newQueryString.split("&")) {
243-
String name = part;
244-
String value = "";
245-
int equals = part.indexOf('=');
246-
if (equals != -1) {
247-
name = part.substring(0, equals);
248-
value = part.substring(equals + 1);
249-
}
250-
Deque<String> queue = newQueryParameters.get(name);
251-
if (queue == null) {
252-
newQueryParameters.put(name, queue = new ArrayDeque<>(1));
253-
}
254-
queue.add(value);
223+
ServletPathMatch info;
224+
try {
225+
info = DispatchUtils.dispatchAsync(path, requestImpl, responseImpl, (ServletContextImpl) context);
226+
} catch (ParameterLimitException e) {
227+
throw new IllegalStateException(e);
255228
}
256-
requestImpl.setQueryParameters(newQueryParameters);
257-
258-
requestImpl.getExchange().setRelativePath(newServletPath);
259-
requestImpl.getExchange().setQueryString(newQueryString);
260-
requestImpl.getExchange().setRequestPath(newRequestUri);
261-
requestImpl.getExchange().setRequestURI(newRequestUri);
262-
requestImpl.setServletContext((ServletContextImpl) context);
263-
responseImpl.setServletContext((ServletContextImpl) context);
264229

265230
Deployment deployment = requestImpl.getServletContext().getDeployment();
266-
ServletPathMatch info = deployment.getServletPaths().getServletHandlerByPath(newServletPath);
267-
requestImpl.getExchange().getAttachment(ServletRequestContext.ATTACHMENT_KEY).setServletPathMatch(info);
268-
269231
dispatchAsyncRequest(deployment.getServletDispatcher(), info, exchange);
270232
}
271233

servlet/src/main/java/io/undertow/servlet/spec/HttpServletRequestImpl.java

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
package io.undertow.servlet.spec;
2020

21-
import io.undertow.UndertowOptions;
2221
import io.undertow.security.api.SecurityContext;
2322
import io.undertow.security.idm.Account;
2423
import io.undertow.server.HttpServerExchange;
@@ -56,7 +55,6 @@
5655
import java.io.UnsupportedEncodingException;
5756
import java.net.InetAddress;
5857
import java.net.InetSocketAddress;
59-
import java.net.URLDecoder;
6058
import java.nio.charset.Charset;
6159
import java.nio.charset.StandardCharsets;
6260
import java.nio.charset.UnsupportedCharsetException;
@@ -291,29 +289,16 @@ public String getMethod() {
291289

292290
@Override
293291
public String getPathInfo() {
294-
final ServletPathMatch match = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletPathMatch();
295-
return match != null ? decodeURL(match.getRemaining()) : null;
296-
}
297-
298-
private String decodeURL(final String s) {
299-
try {
300-
return s != null && s.length() > 0 ? URLDecoder.decode(s, getURLEncoding()) : s;
301-
} catch (UnsupportedEncodingException ignored) {
302-
throw new IllegalStateException(); // cannot happen
292+
ServletPathMatch match = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletPathMatch();
293+
if (match != null) {
294+
return match.getRemaining();
303295
}
304-
}
305-
306-
private String getURLEncoding() {
307-
return exchange.getConnection().getUndertowOptions().get(UndertowOptions.URL_CHARSET, StandardCharsets.UTF_8.name());
296+
return null;
308297
}
309298

310299
@Override
311300
public String getPathTranslated() {
312-
ServletPathMatch match = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletPathMatch();
313-
if (match != null) {
314-
return servletContext.getRealPath(match.getRemaining());
315-
}
316-
return null;
301+
return servletContext.getRealPath(getPathInfo());
317302
}
318303

319304
@Override
@@ -453,8 +438,11 @@ public StringBuffer getRequestURL() {
453438

454439
@Override
455440
public String getServletPath() {
456-
final ServletPathMatch match = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletPathMatch();
457-
return match != null ? decodeURL(match.getMatched()) : "";
441+
ServletPathMatch match = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletPathMatch();
442+
if (match != null) {
443+
return match.getMatched();
444+
}
445+
return "";
458446
}
459447

460448
@Override
@@ -1183,11 +1171,7 @@ public String getOriginalServletPath() {
11831171
if(uri != null) {
11841172
return uri;
11851173
}
1186-
ServletPathMatch match = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletPathMatch();
1187-
if (match != null) {
1188-
return match.getMatched();
1189-
}
1190-
return "";
1174+
return getServletPath();
11911175
}
11921176

11931177
public String getOriginalPathInfo() {
@@ -1199,11 +1183,7 @@ public String getOriginalPathInfo() {
11991183
if(uri != null) {
12001184
return uri;
12011185
}
1202-
ServletPathMatch match = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletPathMatch();
1203-
if (match != null) {
1204-
return match.getRemaining();
1205-
}
1206-
return null;
1186+
return getPathInfo();
12071187
}
12081188

12091189
public String getOriginalContextPath() {

0 commit comments

Comments
 (0)