This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 137f8d30e109a0f62facc5a27b7b71c89775ca36 Author: opencode <[email protected]> AuthorDate: Sun Oct 18 16:20:23 2026 +0200 Reduce the cost of parsing EL expressions with long tokens The character stream used by the EL parser grew its buffer by a fixed 2048 characters on each expansion, copying the existing contents on every expansion. Reading a single token larger than the initial buffer, such as a long string literal, therefore required one expansion per 2048 characters read and copied everything read so far on each of those expansions. The total cost grew quadratically with the token length: a one megabyte string literal took around 640ms to parse and a ten megabyte one over thirty seconds. Grow the buffer in proportion to its current size, doubling it, so the number of expansions and the total copy cost grow linearly with the input. The arithmetic that relocates the current token uses the previous buffer size throughout and is unaffected. Parsing the same expressions now takes a few tens of milliseconds with identical results, including the error positions reported for invalid expressions. --- java/org/apache/el/parser/SimpleCharStream.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/java/org/apache/el/parser/SimpleCharStream.java b/java/org/apache/el/parser/SimpleCharStream.java index d68f7c54cb..1a84886078 100644 --- a/java/org/apache/el/parser/SimpleCharStream.java +++ b/java/org/apache/el/parser/SimpleCharStream.java @@ -58,9 +58,15 @@ public class SimpleCharStream { protected void ExpandBuff(boolean wrapAround) { - char[] newbuffer = new char[bufsize + 2048]; - int newbufline[] = new int[bufsize + 2048]; - int newbufcolumn[] = new int[bufsize + 2048]; + // Grow the buffer geometrically. Growing by a fixed amount, as was + // done previously, makes the total cost of reading a single token + // that is larger than the initial buffer quadratic, since the entire + // contents of the buffer are copied on every expansion. + int newbufsize = (int) Math.min((long) bufsize * 2, Integer.MAX_VALUE); + + char[] newbuffer = new char[newbufsize]; + int newbufline[] = new int[newbufsize]; + int newbufcolumn[] = new int[newbufsize]; try { if (wrapAround) { @@ -93,7 +99,7 @@ public class SimpleCharStream { throw new Error(t.getMessage()); } - bufsize += 2048; + bufsize = newbufsize; available = bufsize; tokenBegin = 0; } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
