From: Markus Koschany Date: Tue, 26 Sep 2023 21:06:42 +0200 Subject: CVE-2023-40167 Origin: https://github.com/eclipse/jetty.project/commit/e4d596eafc887bcd813ae6e28295b5ce327def47 --- .../java/org/eclipse/jetty/http/HttpParser.java | 47 +++++++------- .../org/eclipse/jetty/http/HttpParserTest.java | 71 +++++----------------- 2 files changed, 38 insertions(+), 80 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index 2abc4b6..c045498 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -501,7 +501,7 @@ public class HttpParser /* Quick lookahead for the start state looking for a request method or a HTTP version, * otherwise skip white space until something else to parse. */ - private boolean quickStart(ByteBuffer buffer) + private void quickStart(ByteBuffer buffer) { if (_requestHandler!=null) { @@ -512,7 +512,7 @@ public class HttpParser buffer.position(buffer.position()+_methodString.length()+1); setState(State.SPACE1); - return false; + return; } } else if (_responseHandler!=null) @@ -522,7 +522,7 @@ public class HttpParser { buffer.position(buffer.position()+_version.asString().length()+1); setState(State.SPACE1); - return false; + return; } } @@ -543,7 +543,7 @@ public class HttpParser _string.setLength(0); _string.append(t.getChar()); setState(_requestHandler!=null?State.METHOD:State.RESPONSE_VERSION); - return false; + return; } case OTEXT: case SPACE: @@ -561,7 +561,6 @@ public class HttpParser throw new BadMessageException(HttpStatus.BAD_REQUEST_400); } } - return false; } /* ------------------------------------------------------------------------------- */ @@ -979,12 +978,13 @@ public class HttpParser switch (_header) { case CONTENT_LENGTH: + long contentLength = convertContentLength(_valueString); if (_hasContentLength) { if(complianceViolation(MULTIPLE_CONTENT_LENGTHS)) throw new BadMessageException(HttpStatus.BAD_REQUEST_400,MULTIPLE_CONTENT_LENGTHS.description); - if (convertContentLength(_valueString)!=_contentLength) - throw new BadMessageException(HttpStatus.BAD_REQUEST_400,MULTIPLE_CONTENT_LENGTHS.description); + if (contentLength != _contentLength) + throw new BadMessageException(HttpStatus.BAD_REQUEST_400, MULTIPLE_CONTENT_LENGTHS.getDescription()); } _hasContentLength = true; @@ -993,11 +993,8 @@ public class HttpParser if (_endOfContent != EndOfContent.CHUNKED_CONTENT) { - _contentLength=convertContentLength(_valueString); - if (_contentLength <= 0) - _endOfContent=EndOfContent.NO_CONTENT; - else - _endOfContent=EndOfContent.CONTENT_LENGTH; + _contentLength = contentLength; + _endOfContent = EndOfContent.CONTENT_LENGTH; } break; @@ -1085,15 +1082,21 @@ public class HttpParser private long convertContentLength(String valueString) { - try - { - return Long.parseLong(valueString); - } - catch(NumberFormatException e) + if (valueString == null || valueString.length() == 0) + throw new BadMessageException("Invalid Content-Length Value", new NumberFormatException()); + + long value = 0; + int length = valueString.length(); + + for (int i = 0; i < length; i++) { - LOG.ignore(e); - throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Invalid Content-Length Value",e); + char c = valueString.charAt(i); + if (c < '0' || c > '9') + throw new BadMessageException("Invalid Content-Length Value", new NumberFormatException()); + + value = Math.addExact(Math.multiplyExact(value, 10L), c - '0'); } + return value; } /* ------------------------------------------------------------------------------- */ @@ -1485,12 +1488,11 @@ public class HttpParser _methodString=null; _endOfContent=EndOfContent.UNKNOWN_CONTENT; _header=null; - if (quickStart(buffer)) - return true; + quickStart(buffer); } // Request/response line - if (_state.ordinal()>= State.START.ordinal() && _state.ordinal() _fields = new ArrayList<>(); - private List _trailers = new ArrayList<>(); + private final List _fields = new ArrayList<>(); + private final List _trailers = new ArrayList<>(); private String[] _hdr; private String[] _val; private int _headers;