[jboss-jira] [JBoss JIRA] (JBEE-183) NullPointerException happens at ELEvaluator.parseExpressionString() due to a concurrency issue

Scott Marlow (JIRA) issues at jboss.org
Thu Dec 7 08:47:00 EST 2017


    [ https://issues.jboss.org/browse/JBEE-183?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13502971#comment-13502971 ] 

Scott Marlow commented on JBEE-183:
-----------------------------------

Might it be that org.apache.taglibs.standard.lang.jstl.ELEvaluator.parseExpressionString is the victim of 'mBypassCache' being false initially (so we skip call to 'createExpressionStringMap') but later being true (likely from activity on different thread) at the time that we reach the subsequent use of (null) createExpressionStringMap.

Could we preallocate the sCachedExpressionStrings?

> NullPointerException happens at ELEvaluator.parseExpressionString() due to a concurrency issue
> ----------------------------------------------------------------------------------------------
>
>                 Key: JBEE-183
>                 URL: https://issues.jboss.org/browse/JBEE-183
>             Project: JBoss JavaEE Spec APIs
>          Issue Type: Bug
>          Components: jboss-jstl-api
>         Environment: - JBoss EAP 7.0.8
> - jboss-jstl-api_1.2_spec-1.1.3.Final
>            Reporter: Masafumi Miura
>            Assignee: Tomas Hofman
>         Attachments: byteman-script.btm, example.zip
>
>
> The following NullPointerException happens at ELEvaluator.parseExpressionString() due to a concurrency issue. 
> Once this NPE happens, you will see same NPE every time when accessing the failed JSP. (If development="true" is configured in <jsp-config>, recompile can happen in the next access, so NPE can disappear after successful compilation in the next access.)
> {code}
> ERROR [io.undertow.request] (default task-4) UT005023: Exception handling request to /dsl/g/clsys/cl/nop-constind/CNC001.jsp: org.apache.jasper.JasperException: JBWEB004001: Unable to compile class for JSP
>     at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:667) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:358) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:402) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:346) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final-redhat-1.jar:1.0.0.Final-redhat-1]
>     ...(snip)...
>     ...
> Caused by: java.lang.NullPointerException
>     at org.apache.taglibs.standard.lang.jstl.ELEvaluator.parseExpressionString(ELEvaluator.java:276) [jboss-jstl-api_1.2_spec-1.1.3.Final-redhat-1.jar:1.1.3.Final-redhat-1]
>     at org.apache.taglibs.standard.lang.jstl.Evaluator.validate(Evaluator.java:71) [jboss-jstl-api_1.2_spec-1.1.3.Final-redhat-1.jar:1.1.3.Final-redhat-1]
>     at org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager.validate(ExpressionEvaluatorManager.java:131) [jboss-jstl-api_1.2_spec-1.1.3.Final-redhat-1.jar:1.1.3.Final-redhat-1]
>     at org.apache.taglibs.standard.tlv.el.ValidationUtil.validateExpression(ValidationUtil.java:26) [jboss-jstl-api_1.2_spec-1.1.3.Final-redhat-1.jar:1.1.3.Final-redhat-1]
>     at org.apache.taglibs.standard.tlv.el.JstlELCoreTLV.validateExpression(JstlELCoreTLV.java:26) [jboss-jstl-api_1.2_spec-1.1.3.Final-redhat-1.jar:1.1.3.Final-redhat-1]
>     at org.apache.taglibs.standard.tlv.JstlCoreTLV$Handler.startElement(JstlCoreTLV.java:158) [jboss-jstl-api_1.2_spec-1.1.3.Final-redhat-1.jar:1.1.3.Final-redhat-1]
>     at org.apache.xerces.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:498)
>     at org.apache.xerces.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:180)
>     at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:275)
>     at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(XMLDocumentFragmentScannerImpl.java:1653)
>     at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:324)
>     at org.apache.xerces.parsers.XML11Configuration.parse(XML11Configuration.java:875)
>     at org.apache.xerces.parsers.XML11Configuration.parse(XML11Configuration.java:798)
>     at org.apache.xerces.parsers.XMLParser.parse(XMLParser.java:108)
>     at org.apache.xerces.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1198)
>     at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:564)
>     at org.apache.taglibs.standard.tlv.JstlBaseTLV.validate(JstlBaseTLV.java:158) [jboss-jstl-api_1.2_spec-1.1.3.Final-redhat-1.jar:1.1.3.Final-redhat-1]
>     at org.apache.taglibs.standard.tlv.JstlCoreTLV.validate(JstlCoreTLV.java:97) [jboss-jstl-api_1.2_spec-1.1.3.Final-redhat-1.jar:1.1.3.Final-redhat-1]
>     at org.apache.jasper.compiler.TagLibraryInfoImpl.validate(TagLibraryInfoImpl.java:552) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.compiler.Validator.validateXmlView(Validator.java:1856) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.compiler.Validator.validateExDirectives(Validator.java:1825) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:218) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.compiler.Compiler.compile(Compiler.java:354) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.compiler.Compiler.compile(Compiler.java:334) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.compiler.Compiler.compile(Compiler.java:321) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:652) [jastow-2.0.0.Final-redhat-1.jar:2.0.0.Final-redhat-1]
>     ... 61 more
> {code}
> - https://github.com/jboss/jboss-jstl-api_spec/blob/jboss-jstl-api_1.2_spec-1.1.3.Final/src/main/java/org/apache/taglibs/standard/lang/jstl/ELEvaluator.java#L275-L277
> {code}
> 252     public Object parseExpressionString(String pExpressionString)
> 253             throws ELException {
> 254         // See if it's an empty String
> 255         if (pExpressionString.length() == 0) {
> 256             return "";
> 257         }
> 258
> 259         if (!(mBypassCache) && (sCachedExpressionStrings == null)) {
> 260             createExpressionStringMap();
> 261         }
> 262
> 263         // See if it's in the cache
> 264         Object ret =
> 265                 mBypassCache ?
> 266                         null :
> 267                         sCachedExpressionStrings.get(pExpressionString);
> 268
> 269         if (ret == null) {
> 270             // Parse the expression
> 271             Reader r = new StringReader(pExpressionString);
> 272             ELParser parser = new ELParser(r);
> 273             try {
> 274                 ret = parser.ExpressionString();
> 275                 if (!mBypassCache) {
> 276                     sCachedExpressionStrings.put(pExpressionString, ret); // <- NPE occurred at here
> 277                 }
> 278             }
> 279             catch (ParseException exc) {
> 280                 throw new ELException
> 281                         (formatParseException(pExpressionString,
> 282                                 exc));
> 283             }
> 284             catch (TokenMgrError exc) {
> 285                 // Note - this should never be reached, since the parser is
> 286                 // constructed to tokenize any input (illegal inputs get
> 287                 // parsed to <BADLY_ESCAPED_STRING_LITERAL> or
> 288                 // <ILLEGAL_CHARACTER>
> 289                 throw new ELException(exc.getMessage());
> 290             }
> 291         }
> 292         return ret;
> 293     }
> {code}
> - https://github.com/jboss/jboss-jstl-api_spec/blob/jboss-jstl-api_1.2_spec-1.1.3.Final/src/main/java/org/apache/taglibs/standard/lang/jstl/Evaluator.java#L70-L71
> {code}
> ~~~
>  51     /**
>  52      * The singleton instance of the evaluator *
>  53      */
>  54     static ELEvaluator sEvaluator =
>  55             new ELEvaluator
>  56                     (new JSTLVariableResolver());
>  :
>  62     /**
>  63      * Translation time validation of an attribute value.  This method
>  64      * will return a null String if the attribute value is valid;
>  65      * otherwise an error message.
>  66      */
>  67     public String validate(String pAttributeName,
>  68                            String pAttributeValue) {
>  69         try {
>  70             sEvaluator.setBypassCache(true);   // <-- mBypassCache is set to true before invoking parseExpressionString()
>  71             sEvaluator.parseExpressionString(pAttributeValue);
>  72             sEvaluator.setBypassCache(false);
>  73             return null;
>  74         }
>  75         catch (ELException exc) {
> {code}



--
This message was sent by Atlassian JIRA
(v7.5.0#75005)


More information about the jboss-jira mailing list