You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@struts.apache.org by "David Greene (JIRA)" <ji...@apache.org> on 2013/07/12 16:17:48 UTC
[jira] [Comment Edited] (WW-4138) OgnlTextParser contains a NPE
when the expression is passed in as null
[ https://issues.apache.org/jira/browse/WW-4138?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13706967#comment-13706967 ]
David Greene edited comment on WW-4138 at 7/12/13 2:17 PM:
-----------------------------------------------------------
The line number is a little bit off of the 2.3.15 compiled class because we have a built-in code formatter. Here's our autoformatted class (which should be identical sans whitespace to the one in the 2.3.15 release:
{code}
package com.opensymphony.xwork2.util;
import org.apache.commons.lang3.StringUtils;
/**
* OGNL implementation of {@link TextParser}
*/
public class OgnlTextParser
implements TextParser
{
//~ Methods ----------------------------------------------------------------
public Object evaluate( char openChars[],
String expression,
TextParseUtil.ParsedValueEvaluator evaluator,
int maxLoopCount )
{
// deal with the "pure" expressions first!
//expression = expression.trim();
Object result = expression; // = ( expression == null ) ? "" : expression;
int pos = 0;
for ( char open : openChars )
{
int loopCount = 1;
//this creates an implicit StringBuffer and shouldn't be used in the inner loop
final String lookupChars = open + "{";
while ( true )
{
int start = expression.indexOf( lookupChars, pos );
if ( start == -1 )
{
loopCount++;
start = expression.indexOf( lookupChars );
}
if ( loopCount > maxLoopCount )
{
// translateVariables prevent infinite loop / expression recursive evaluation
break;
}
int length = expression.length( );
int x = start + 2;
int end;
char c;
int count = 1;
while ( ( start != -1 ) && ( x < length ) && ( count != 0 ) )
{
c = expression.charAt( x++ );
if ( c == '{' )
{
count++;
}
else if ( c == '}' )
{
count--;
}
}
end = x - 1;
if ( ( start != -1 ) && ( end != -1 ) && ( count == 0 ) )
{
String var = expression.substring( start + 2, end );
Object o = evaluator.evaluate( var );
String left = expression.substring( 0, start );
String right = expression.substring( end + 1 );
String middle = null;
if ( o != null )
{
middle = o.toString( );
if ( StringUtils.isEmpty( left ) )
{
result = o;
}
else
{
result = left.concat( middle );
}
if ( StringUtils.isNotEmpty( right ) )
{
result = result.toString( ).concat( right );
}
expression = left.concat( middle ).concat( right );
}
else
{
// the variable doesn't exist, so don't display anything
expression = left.concat( right );
result = expression;
}
pos = ( ( ( left != null ) && ( left.length( ) > 0 ) )
? ( left.length( ) - 1 )
: 0 ) + ( ( ( middle != null ) && ( middle.length( ) > 0 ) )
? ( middle.length( ) - 1 )
: 0 ) + 1;
pos = Math.max( pos, 1 );
}
else
{
break;
}
}
}
return result;
}
}
{code}
was (Author: trumpetx):
The line number is a little bit off of the 2.3.15 compiled class because we have a built-in code formatter. Here's our autoformatted class (which should be identical to the one in the 2.3.15 release:
{code}
package com.opensymphony.xwork2.util;
import org.apache.commons.lang3.StringUtils;
/**
* OGNL implementation of {@link TextParser}
*/
public class OgnlTextParser
implements TextParser
{
//~ Methods ----------------------------------------------------------------
public Object evaluate( char openChars[],
String expression,
TextParseUtil.ParsedValueEvaluator evaluator,
int maxLoopCount )
{
// deal with the "pure" expressions first!
//expression = expression.trim();
Object result = expression; // = ( expression == null ) ? "" : expression;
int pos = 0;
for ( char open : openChars )
{
int loopCount = 1;
//this creates an implicit StringBuffer and shouldn't be used in the inner loop
final String lookupChars = open + "{";
while ( true )
{
int start = expression.indexOf( lookupChars, pos );
if ( start == -1 )
{
loopCount++;
start = expression.indexOf( lookupChars );
}
if ( loopCount > maxLoopCount )
{
// translateVariables prevent infinite loop / expression recursive evaluation
break;
}
int length = expression.length( );
int x = start + 2;
int end;
char c;
int count = 1;
while ( ( start != -1 ) && ( x < length ) && ( count != 0 ) )
{
c = expression.charAt( x++ );
if ( c == '{' )
{
count++;
}
else if ( c == '}' )
{
count--;
}
}
end = x - 1;
if ( ( start != -1 ) && ( end != -1 ) && ( count == 0 ) )
{
String var = expression.substring( start + 2, end );
Object o = evaluator.evaluate( var );
String left = expression.substring( 0, start );
String right = expression.substring( end + 1 );
String middle = null;
if ( o != null )
{
middle = o.toString( );
if ( StringUtils.isEmpty( left ) )
{
result = o;
}
else
{
result = left.concat( middle );
}
if ( StringUtils.isNotEmpty( right ) )
{
result = result.toString( ).concat( right );
}
expression = left.concat( middle ).concat( right );
}
else
{
// the variable doesn't exist, so don't display anything
expression = left.concat( right );
result = expression;
}
pos = ( ( ( left != null ) && ( left.length( ) > 0 ) )
? ( left.length( ) - 1 )
: 0 ) + ( ( ( middle != null ) && ( middle.length( ) > 0 ) )
? ( middle.length( ) - 1 )
: 0 ) + 1;
pos = Math.max( pos, 1 );
}
else
{
break;
}
}
}
return result;
}
}
{code}
> OgnlTextParser contains a NPE when the expression is passed in as null
> ----------------------------------------------------------------------
>
> Key: WW-4138
> URL: https://issues.apache.org/jira/browse/WW-4138
> Project: Struts 2
> Issue Type: Bug
> Affects Versions: 2.3.15
> Reporter: David Greene
> Fix For: 2.3.16
>
>
> Unfortunately, I haven't figured out the exact cause of the issue; however, the fix provided brings our system back to how it used to work.
> When expression is passed in a null, a NPE is thrown @:
> int start = expression.indexOf(lookupChars, pos);
> {code}
> Object result = expression;
> int pos = 0;
> for (char open : openChars) {
> int loopCount = 1;
> //this creates an implicit StringBuffer and shouldn't be used in the inner loop
> final String lookupChars = open + "{";
> while (true) {
> int start = expression.indexOf(lookupChars, pos);
> if (start == -1) {
> loopCount++;
> start = expression.indexOf(lookupChars);
> }
> {code}
> Here is the fix I'm using in a locally built class file:
> {code}
> Object result = expression = (expression == null) ? "" : expression;
> int pos = 0;
> for (char open : openChars) {
> int loopCount = 1;
> //this creates an implicit StringBuffer and shouldn't be used in the inner loop
> final String lookupChars = open + "{";
> while (true) {
> int start = expression.indexOf(lookupChars, pos);
> if (start == -1) {
> loopCount++;
> start = expression.indexOf(lookupChars);
> }
> {code}
> I can see about 10 different ways to 'fix' the issue, but this keeps the change to a single line since I don't entirely understand the workflow of what's going on.
> FYI, it seems to have something to do with validate="true" on the form and when there are fields to validate which have nested getters, aka:
> <@s.hidden key="myFakePatternHolder.pattern.id"/>
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira