question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SpEL vararg method invocation fails if string literal contains a comma

See original GitHub issue

Affects: 4.1.2 and up

I’m trying to use my own matching functions with spring-expression, but I came across a possible bug.

Here’s some code for context:

import org.springframework.expression.spel.support.StandardEvaluationContext;

public class RuleEvaluationContext extends StandardEvaluationContext {

	public RuleEvaluationContext(Object rootObject) {
		super(rootObject);
		registerFunctions();
	}

	public RuleEvaluationContext() {
		super();
		registerFunctions();
	}

	private void registerFunctions() {
		for (Functions fun : Functions.values()) {
			this.registerFunction(fun.funcName(), fun.method());
		}
	}

}
enum Functions {
/* Functions commented for the sake of simplicity

	CONTAINS(Contains.FUNC_NAME,
		getDeclaredMethod(Contains.class, Contains.FUNC_NAME, String.class, String[].class)),

	STARTS_WITH(StartsWith.FUNC_NAME,
		getDeclaredMethod(StartsWith.class, StartsWith.FUNC_NAME, String.class, String[].class)),
*/

	MATCHES(Matches.FUNC_NAME,
		getDeclaredMethod(Matches.class, Matches.FUNC_NAME, String.class, String[].class)),
/*
	EQUALS(Equals.FUNC_NAME,
		getDeclaredMethod(Equals.class, Equals.FUNC_NAME, String.class, String.class)),

	GREATER(GreaterThan.FUNC_NAME,
		getDeclaredMethod(GreaterThan.class, GreaterThan.FUNC_NAME, String.class, String.class)),

	LESS_THAN(LessThan.FUNC_NAME,
		getDeclaredMethod(LessThan.class, LessThan.FUNC_NAME, String.class, String.class));
*/

	private final String funcName;
	private final Method method;

	Functions(String funcName, Method method) {
		this.funcName = funcName;
		this.method = method;
	}

	public String funcName() {
		return funcName;
	}

	public Method method() {
		return method;
	}

	private static Method getDeclaredMethod(Class c, String name, Class<?>... parameterTypes) {
		try {
			return c.getDeclaredMethod(name, parameterTypes);
		} catch (NoSuchMethodException e) {
			throw new FunctionsException(e);
		}
	}

}

This is one of the registered functions:

public class Matches {

	public static final String FUNC_NAME = "matches";

	private Matches() {
		super();
	}

	public static boolean matches(String text, String... regexps) {
		if (text != null) {
			for (String regex : regexps) {
				Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
				Matcher matcher = pattern.matcher(text);
				if (matcher.find()) {
					return true;
				}
			}
		}
		return false;
	}
}
@Test
public void test() {
	final RuleEvaluationContext context = new RuleEvaluationContext(new FakeObject());
	String originalRule = "#matches(prop, 'xyz,xyz')";
	Expression expression = parser.parseExpression(originalRule);
	Boolean result = expression.getValue(context, Boolean.class);
	assertThat(result, is(false));
}

private final ExpressionParser parser = new SpelExpressionParser();

private static class FakeObject {
	private String prop = "xyz";

	public String getProp() {
		return prop;
	}
}

This test fails when it should pass. Upon further inspection I’ve found that the problem is that spring-expression breaks the ‘xyz,xyz’ into [“xyz”, “xyz”] as can be seen below.

libnova

However I’ve also found that using old versions of the library (pre 4.1.2), this doesn’t happen.

libantiga

As does putting more strings inside the argument:

@Test
public void test() {
	final RuleEvaluationContext context = new RuleEvaluationContext(new FakeObject());
	String originalRule = "#matches(prop, 'abc', 'xyz,xyz')";
	Expression expression = parser.parseExpression(originalRule);
	Boolean result = expression.getValue(context, Boolean.class);
	assertThat(result, is(false));
}

libnovasembug

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:11 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
sbrannencommented, Oct 21, 2021

I have confirmed that this is a bug which applies to method invocations in general (not just to custom functions).

1reaction
sbrannencommented, Oct 22, 2021

@bmoraes-axur, feel free to try this out in the next 5.3.13 snapshot and let us know if you run into any issues.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Passing varargs to Spring spEL causes "Method cannot be ...
As shown this method takes varargs of String type. It works fine when only one parameter is passed (as on the example above)...
Read more >
[GitHub] [maven-indexer] dependabot[bot] opened a new pull ...
... <li>SpEL vararg method invocation fails if string literal contains a comma <a ...
Read more >
8. Spring Expression Language (SpEL)
As an example of method invocation, we call the 'concat' method on the string literal. ExpressionParser parser = new SpelExpressionParser(); Expression exp ...
Read more >
Spring Security – Access Denied SpEL Changes - Europheus
This is a result of this change in 5.3.13. SpEL vararg method invocation fails if string literal contains a comma #27582 ...
Read more >
Mypy Documentation - Read the Docs
These calls will fail when the program run, but mypy does not report an error. # because "greeting" does not have type annotations....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found