Parse entire HTTP chunk size #396 (#528)
* Parse entire HTTP chunk size #396
Continue parsing HTTP chunk size up until Int.MaxValue so the actual
size of the chunk can be logged if it exceeds the configured max chunk
size.
* Add reference to Integer.MAX_VALUE in the error message
* Fix formatting
diff --git a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/parsing/HttpMessageParser.scala b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/parsing/HttpMessageParser.scala
index ea7edcc..374f3c3 100644
--- a/http-core/src/main/scala/org/apache/pekko/http/impl/engine/parsing/HttpMessageParser.scala
+++ b/http-core/src/main/scala/org/apache/pekko/http/impl/engine/parsing/HttpMessageParser.scala
@@ -307,17 +307,20 @@
s"HTTP chunk extension length exceeds configured limit of ${settings.maxChunkExtLength} characters")
@tailrec def parseSize(cursor: Int, size: Long): StateResult =
- if (size <= settings.maxChunkSize) {
+ if (size <= Int.MaxValue) {
byteChar(input, cursor) match {
case c if CharacterClasses.HEXDIG(c) => parseSize(cursor + 1, size * 16 + CharUtils.hexValue(c))
- case ';' if cursor > offset => parseChunkExtensions(size.toInt, cursor + 1)()
+ case c if size > settings.maxChunkSize =>
+ failEntityStream(
+ s"HTTP chunk of $size bytes exceeds the configured limit of ${settings.maxChunkSize} bytes")
+ case ';' if cursor > offset => parseChunkExtensions(size.toInt, cursor + 1)()
case '\r' if cursor > offset && byteChar(input, cursor + 1) == '\n' =>
parseChunkBody(size.toInt, "", cursor + 2)
case '\n' if cursor > offset => parseChunkBody(size.toInt, "", cursor + 1)
case c if CharacterClasses.WSP(c) => parseSize(cursor + 1, size) // illegal according to the spec but can happen, see issue #1812
case c => failEntityStream(s"Illegal character '${escape(c)}' in chunk start")
}
- } else failEntityStream(s"HTTP chunk size exceeds the configured limit of ${settings.maxChunkSize} bytes")
+ } else failEntityStream(s"HTTP chunk size exceeds Integer.MAX_VALUE (${Int.MaxValue}) bytes")
try parseSize(offset, 0)
catch {
diff --git a/http-core/src/test/scala/org/apache/pekko/http/impl/engine/parsing/RequestParserSpec.scala b/http-core/src/test/scala/org/apache/pekko/http/impl/engine/parsing/RequestParserSpec.scala
index 7b6d807..fbbbec7 100644
--- a/http-core/src/test/scala/org/apache/pekko/http/impl/engine/parsing/RequestParserSpec.scala
+++ b/http-core/src/test/scala/org/apache/pekko/http/impl/engine/parsing/RequestParserSpec.scala
@@ -531,13 +531,24 @@
closeAfterResponseCompletion shouldEqual Seq(false)
}
- "too-large chunk size" in new Test {
+ "too-large chunk size (> Int.MaxValue)" in new Test {
Seq(
start,
"""1a2b3c4d5e
|""") should generalMultiParseTo(
Right(baseRequest),
- Left(EntityStreamError(ErrorInfo("HTTP chunk size exceeds the configured limit of 1048576 bytes"))))
+ Left(EntityStreamError(ErrorInfo("HTTP chunk size exceeds Integer.MAX_VALUE (2147483647) bytes"))))
+ closeAfterResponseCompletion shouldEqual Seq(false)
+ }
+
+ "too-large chunk size" in new Test {
+ Seq(
+ start,
+ """400000
+ |""") should generalMultiParseTo(
+ Right(baseRequest),
+ Left(
+ EntityStreamError(ErrorInfo("HTTP chunk of 4194304 bytes exceeds the configured limit of 1048576 bytes"))))
closeAfterResponseCompletion shouldEqual Seq(false)
}