Skip to content

NPE in FunctionReference due to race condition in SpelExpression.getValue() [SPR-16255] #20802

@spring-projects-issues

Description

@spring-projects-issues

Alvaro Manuel Recio Perez opened SPR-16255 and commented

We have issues in a scenario in which several threads are evaluating the same expression (which include functions) in IMMEDIATE mode.

org.springframework.expression.spel.standard.getValue() includes the following piece of code:

Object result = this.ast.getValue(expressionState);
checkCompile(expressionState);

The call to checkCompile() goes through a synchronized block in compileExpression() which ends up in org.springframework.expression.spel.ast.FunctionReference.generateCode(). Inside this method, the field this.method is accessed twice, as follows:

@Override 
public void generateCode(MethodVisitor mv,CodeFlow cf) {
     Assert.state(this.method != null, "No method handle");
     String classDesc = this.method.getDeclaringClass().getName().replace('.', '/');
     generateCodeForArguments(mv, cf, this.method, this.children);
     mv.visitMethodInsn(INVOKESTATIC, classDesc, this.method.getName(),
               CodeFlow.createSignatureDescriptor(this.method), false);
     cf.pushDescriptor(this.exitTypeDescriptor);
}

However, the call to this.ast.getValue(expressionState) in org.springframework.expression.spel.standard.getValue() we saw earlier, which does not go through a synchronized block, ends up calling org.springframework.expression.spel.ast.FunctionReference.executeFunctionJLRMethod(). The first insruction of this method is:

private TypedValue executeFunctionJLRMethod(ExpressionState state, Method method) throws EvaluationException {
     this.method = null;

Because this code path is not synchronized, it may set this.method to null while the thread executing checkCompile() is running, causing a NullPointerException:

Exception in thread "Thread-95499" java.lang.NullPointerException
	at org.springframework.expression.spel.ast.FunctionReference.generateCode(FunctionReference.java:184)
	at org.springframework.expression.spel.standard.SpelCompiler.createExpressionClass(SpelCompiler.java:160)
	at org.springframework.expression.spel.standard.SpelCompiler.compile(SpelCompiler.java:105)
	at org.springframework.expression.spel.standard.SpelExpression.compileExpression(SpelExpression.java:467)
	at org.springframework.expression.spel.standard.SpelExpression.checkCompile(SpelExpression.java:437)
	at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:243)

Affects: 4.3.13, 5.0.2

Referenced from: commits 6a1fe0b, a9bad58

Backported to: 4.3.14

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions