Skip to content

SpEL vararg method invocation fails if string literal contains a comma #27582

Closed
@bmoraes-axur

Description

@bmoraes-axur

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

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions