Bug 66325 - NestedState concurrency issue
Summary: NestedState concurrency issue
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: EL (show other bugs)
Version: 8.5.69
Hardware: Other Linux
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-10-26 10:57 UTC by manuelramonleonjimenez
Modified: 2022-10-28 08:26 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description manuelramonleonjimenez 2022-10-26 10:57:59 UTC
We faced a jsp exception because the nestedState object is not properly synchronized. Even though the line triggering the exception is commented with "Should never happen", it happened to us making the page break.

The lines involved are:

<c:set var="aName">
   <c:out value="${someVariable.stream().filter(i -> i.getEvent() == 'a-value').map(e -> e.getAsJson()).findFirst().orElse('')}" />
</c:set>

The error is:

SEVERE: Servlet.service() for servlet [bestsecret] in context with path [] threw exception [An exception occurred processing [/...] at line ...

...
java.lang.IllegalStateException: Nested state may only be set once
	at org.apache.el.parser.AstLambdaExpression.setNestedState(AstLambdaExpression.java:123)
	at org.apache.el.parser.AstLambdaExpression.getNestedState(AstLambdaExpression.java:114)
	at org.apache.el.parser.AstLambdaExpression.getValue(AstLambdaExpression.java:43)
	at org.apache.el.parser.AstMethodParameters.getParameters(AstMethodParameters.java:33)
	at org.apache.el.parser.AstValue.getValue(AstValue.java:157)
	at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)

Lines with the issue: https://github.com/apache/tomcat/blob/main/java/org/apache/el/parser/AstLambdaExpression.java#L112-L124

The issue IMO is that between the check at line 113 and the check at line 121, the nestedState is set, so the execution enters in the if triggering the unexpected exception, breaking the whole JSP page. The blocks should be synchronized on the object or any other measure taken.

Please fix it as you consider the better.
Comment 1 Mark Thomas 2022-10-27 14:15:09 UTC
Thanks for the report.

The NestedState instance shouldn't be part of the AstLambdaExpression as expressions are cached (parsing is expensive).

It looks like moving the NestedState to the EvaluationContext should fix this. I'm looking at that now.
Comment 2 Mark Thomas 2022-10-27 19:58:11 UTC
Unfortunately the fix isn't going to be that simple. Still exploring options.
Comment 3 Mark Thomas 2022-10-28 08:26:41 UTC
Fixed in:
- main
- 10.1.x for 10.1.2 onwards
-  9.0.x for  9.0.69 onwards
-  8.5.x for  8.5.84 onwards

Moving the state to EvaluationContext was the correct fix - just not in the way I had originally thought.