From 04067a06e0451e695cca9dc5f9b29c18e90a5aef Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 28 Oct 2009 21:57:09 +0000 Subject: [PATCH] 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 --- .../expression/spel/ast/OperatorNot.java | 3 ++- .../expression/spel/ast/Ternary.java | 6 ++++++ .../expression/spel/EvaluationTests.java | 18 +++++++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorNot.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorNot.java index 426693e247c..32d179bf15a 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorNot.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/OperatorNot.java @@ -16,6 +16,7 @@ package org.springframework.expression.spel.ast; +import org.springframework.core.convert.TypeDescriptor; import org.springframework.expression.EvaluationException; import org.springframework.expression.spel.ExpressionState; import org.springframework.expression.spel.SpelEvaluationException; @@ -36,7 +37,7 @@ public class OperatorNot extends SpelNodeImpl { // Not is a unary operator so do @Override public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException { 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); } catch (SpelEvaluationException see) { diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Ternary.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Ternary.java index 46f1f389339..3ee71fc88fb 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Ternary.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Ternary.java @@ -19,6 +19,8 @@ package org.springframework.expression.spel.ast; import org.springframework.expression.EvaluationException; import org.springframework.expression.TypedValue; 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". @@ -43,6 +45,10 @@ public class Ternary extends SpelNodeImpl { @Override public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { 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()) { return children[1].getValueInternal(state); } else { diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java index 15c46d39650..264b50fc617 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/EvaluationTests.java @@ -36,6 +36,8 @@ import org.springframework.expression.spel.support.StandardTypeLocator; * Tests the evaluation of real expressions in a real context. * * @author Andy Clement + * @author Mark Fisher + * @since 3.0 */ public class EvaluationTests extends ExpressionTestCase { @@ -296,6 +298,16 @@ public class EvaluationTests extends ExpressionTestCase { 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 @Test public void testAssignmentToVariables01() { @@ -307,7 +319,6 @@ public class EvaluationTests extends ExpressionTestCase { evaluate("2>4?1:2",2,Integer.class); } - @Test public void testTernaryOperator02() { 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); } + @Test(expected = EvaluationException.class) + public void testTernaryOperatorWithNullValue() { + parser.parseExpression("null ? 0 : 1").getValue(); + } + @Test public void testIndexer03() { evaluate("'christian'[8]", "n", String.class);