SPR-6059 Avoiding NPE for unary-not and ternary operators. If the value is null instead of a valid boolean or Boolean, it will now trigger an EvaluationException.
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@2221 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
becf15008c
commit
04067a06e0
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.expression.spel.ast;
|
package org.springframework.expression.spel.ast;
|
||||||
|
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
import org.springframework.expression.spel.SpelEvaluationException;
|
import org.springframework.expression.spel.SpelEvaluationException;
|
||||||
|
|
@ -36,7 +37,7 @@ public class OperatorNot extends SpelNodeImpl { // Not is a unary operator so do
|
||||||
@Override
|
@Override
|
||||||
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
|
public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
|
||||||
try {
|
try {
|
||||||
boolean value = (Boolean)state.convertValue(children[0].getValueInternal(state), BOOLEAN_TYPE_DESCRIPTOR);
|
boolean value = (Boolean) state.convertValue(children[0].getValueInternal(state), TypeDescriptor.valueOf(boolean.class));
|
||||||
return BooleanTypedValue.forValue(!value);
|
return BooleanTypedValue.forValue(!value);
|
||||||
}
|
}
|
||||||
catch (SpelEvaluationException see) {
|
catch (SpelEvaluationException see) {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ package org.springframework.expression.spel.ast;
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
import org.springframework.expression.TypedValue;
|
import org.springframework.expression.TypedValue;
|
||||||
import org.springframework.expression.spel.ExpressionState;
|
import org.springframework.expression.spel.ExpressionState;
|
||||||
|
import org.springframework.expression.spel.SpelEvaluationException;
|
||||||
|
import org.springframework.expression.spel.SpelMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a ternary expression, for example: "someCheck()?true:false".
|
* Represents a ternary expression, for example: "someCheck()?true:false".
|
||||||
|
|
@ -43,6 +45,10 @@ public class Ternary extends SpelNodeImpl {
|
||||||
@Override
|
@Override
|
||||||
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
|
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
|
||||||
Boolean value = children[0].getValue(state, Boolean.class);
|
Boolean value = children[0].getValue(state, Boolean.class);
|
||||||
|
if (value == null) {
|
||||||
|
throw new SpelEvaluationException(getChild(0).getStartPosition(),
|
||||||
|
SpelMessage.TYPE_CONVERSION_ERROR, "null", "boolean");
|
||||||
|
}
|
||||||
if (value.booleanValue()) {
|
if (value.booleanValue()) {
|
||||||
return children[1].getValueInternal(state);
|
return children[1].getValueInternal(state);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ import org.springframework.expression.spel.support.StandardTypeLocator;
|
||||||
* Tests the evaluation of real expressions in a real context.
|
* Tests the evaluation of real expressions in a real context.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Mark Fisher
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class EvaluationTests extends ExpressionTestCase {
|
public class EvaluationTests extends ExpressionTestCase {
|
||||||
|
|
||||||
|
|
@ -296,6 +298,16 @@ public class EvaluationTests extends ExpressionTestCase {
|
||||||
evaluate("!true", "false", Boolean.class);
|
evaluate("!true", "false", Boolean.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnaryNot02() {
|
||||||
|
evaluate("!false", "true", Boolean.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = EvaluationException.class)
|
||||||
|
public void testUnaryNotWithNullValue() {
|
||||||
|
parser.parseExpression("!null").getValue();
|
||||||
|
}
|
||||||
|
|
||||||
// assignment
|
// assignment
|
||||||
@Test
|
@Test
|
||||||
public void testAssignmentToVariables01() {
|
public void testAssignmentToVariables01() {
|
||||||
|
|
@ -307,7 +319,6 @@ public class EvaluationTests extends ExpressionTestCase {
|
||||||
evaluate("2>4?1:2",2,Integer.class);
|
evaluate("2>4?1:2",2,Integer.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTernaryOperator02() {
|
public void testTernaryOperator02() {
|
||||||
evaluate("'abc'=='abc'?1:2",1,Integer.class);
|
evaluate("'abc'=='abc'?1:2",1,Integer.class);
|
||||||
|
|
@ -332,6 +343,11 @@ public class EvaluationTests extends ExpressionTestCase {
|
||||||
evaluate("2>4?(3>2?true:false):(5<3?true:false)",false,Boolean.class);
|
evaluate("2>4?(3>2?true:false):(5<3?true:false)",false,Boolean.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = EvaluationException.class)
|
||||||
|
public void testTernaryOperatorWithNullValue() {
|
||||||
|
parser.parseExpression("null ? 0 : 1").getValue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIndexer03() {
|
public void testIndexer03() {
|
||||||
evaluate("'christian'[8]", "n", String.class);
|
evaluate("'christian'[8]", "n", String.class);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue