Aegis & inheritance in SOAP message is unsafe: Non-existing type in xsi:type 
definition causes java.lang.StackOverflowError
---------------------------------------------------------------------------------------------------------------------------

                 Key: XFIRE-1101
                 URL: http://jira.codehaus.org/browse/XFIRE-1101
             Project: XFire
          Issue Type: Bug
          Components: Aegis Module, Core
    Affects Versions: 1.2.6
         Environment: XFire 1.2.6 & WebSphere Application Server 5.1
            Reporter: Jari Kujansuu
            Assignee: Dan Diephouse
         Attachments: Echo.wsdl, Echo.zip

I have used Aegis and inheritance (http://xfire.codehaus.org/Aegis+Inheritance) 
in my SOAP service and end up to serious problem.

Using inheritance means that client must define xsi:type attribute for element 
in SOAP request to identify used subtype.
With valid SOAP requests everything works just fine.
Unfortunately I don't have control to SOAP clients using my SOAP service and 
thus SOAP service implementation should tolerate invalid SOAP requests.
Problem is that non-existing type definition in xsi:type attribute causes 
java.lang.StackOverflowError and as a result of that application server crashes.

I made a simple example to illustrate the problem based on spring (Echo) 
example coming with XFire distribution.
Original Echo example had one echo method that receives String parameter and 
returns same String back to client.
I just modified it to pass java.lang.Object instead of String.

Echo interface looks like this:

public interface Echo
{
    Object echo(Object in);
}

and implementation class looks like this:

public class EchoImpl implements Echo
{
    public Object echo(Object in)
    {
        System.out.println("Input data: " + in);
        System.out.println("Type of input data: " + in.getClass().getName());
        return in;
    }
}

and I set writeXsiType property to true in xfire-servlet.xml. For simplicity I 
will use basic Java types to which XMLSchema itself defines counterpart as 
arguments.
Following example SOAP requests I have executed using soapUI 
(http://www.soapui.org/) that allows me to easily write SOAP request by myself.

Now following SOAP request works fine:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema";>
        <soap:Body>
                <echo xmlns="http://example.spring.xfire.codehaus.org";>
                        <in0 xsi:type="xsd:string">42</in0>
                </echo>
        </soap:Body>
</soap:Envelope>

SOAP service writes following output as expected:
[11/7/07 17:22:23:937 EET] 10596e5e SystemOut     O Input data: 42
[11/7/07 17:22:23:937 EET] 10596e5e SystemOut     O Type of input data: 
java.lang.String

And client receives following response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
   <soap:Body>
      <ns1:echoResponse xmlns:ns1="http://example.spring.xfire.codehaus.org";>
         <ns1:out xsi:type="xsd:string">42</ns1:out>
      </ns1:echoResponse>
   </soap:Body>
</soap:Envelope>

If I replace xsi:type="xsd:string" with xsi:type="xsd:int" everything works 
fine too just the type of object created by XFire changes to Integer and SOAP 
response also contains xsi:type="xsd:int".

Now if I change type of passed argument to xsi:type="xsd:String" where type 
name contains spelling error (starts with uppercase letter instead of lowercase 
letter, can easily happen when SOAP request is written by human user) then 
XFire ends up to infinite recursion and finally causes 
java.lang.StackOverflowError and whole application server crashes (actually not 
in the first time but after second invalid request). Here is the stacktrace:

[11/7/07 17:25:52:967 EET] 10596e5e WebGroup      E SRVE0026E: [Servlet 
Error]-[Error occured during request processing: null]: 
java.lang.StackOverflowError
        at java.lang.String.hashCode(String.java(Compiled Code))
        at 
com.ctc.wstx.sr.NsAttributeCollector.getValue(NsAttributeCollector.java(Compiled
 Code))
        at 
com.ctc.wstx.sr.BasicStreamReader.getAttributeValue(BasicStreamReader.java(Compiled
 Code))
        at 
org.codehaus.xfire.util.stax.DepthXMLStreamReader.getAttributeValue(DepthXMLStreamReader.java(Compiled
 Code))
        at 
org.codehaus.xfire.util.stax.DepthXMLStreamReader.getAttributeValue(DepthXMLStreamReader.java(Inlined
 Compiled Code))
        at 
org.codehaus.xfire.aegis.stax.ElementReader.getAttributeReader(ElementReader.java(Compiled
 Code))

        ... (ObjectType.readObject method end up to the infinite loop, lots of 
stack trace elements identical to ones in below removed from here)

        at 
org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
        at 
org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
        at 
org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
        at 
org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
        at 
org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
        at 
org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
        at 
org.codehaus.xfire.aegis.type.basic.ObjectType.readObject(ObjectType.java:133)
        at 
org.codehaus.xfire.aegis.AegisBindingProvider.readParameter(AegisBindingProvider.java:169)
        at 
org.codehaus.xfire.service.binding.AbstractBinding.read(AbstractBinding.java:206)
        at 
org.codehaus.xfire.service.binding.WrappedBinding.readMessage(WrappedBinding.java:51)
        at 
org.codehaus.xfire.soap.handler.SoapBodyHandler.invoke(SoapBodyHandler.java:42)
        at 
org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131)
        at 
org.codehaus.xfire.transport.DefaultEndpoint.onReceive(DefaultEndpoint.java:64)
        at 
org.codehaus.xfire.transport.AbstractChannel.receive(AbstractChannel.java:38)
        at 
org.codehaus.xfire.transport.http.XFireServletController.invoke(XFireServletController.java:304)
        at 
org.codehaus.xfire.transport.http.XFireServletController.doService(XFireServletController.java:129)
        at 
org.codehaus.xfire.spring.remoting.XFireServletControllerAdapter.handleRequest(XFireServletControllerAdapter.java:67)
        at 
org.codehaus.xfire.spring.remoting.XFireExporter.handleRequest(XFireExporter.java:48)
        at 
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:44)
        at 
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:717)
        at 
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:658)
        at 
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:392)
        at 
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:357)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
        at 
com.ibm.ws.webcontainer.servlet.StrictServletInstance.doService(StrictServletInstance.java:110)
        at 
com.ibm.ws.webcontainer.servlet.StrictLifecycleServlet._service(StrictLifecycleServlet.java:174)
        at 
com.ibm.ws.webcontainer.servlet.IdleServletState.service(StrictLifecycleServlet.java:313)
        at 
com.ibm.ws.webcontainer.servlet.StrictLifecycleServlet.service(StrictLifecycleServlet.java:116)
        at 
com.ibm.ws.webcontainer.servlet.ServletInstance.service(ServletInstance.java:283)
        at 
com.ibm.ws.webcontainer.servlet.ValidServletReferenceState.dispatch(ValidServletReferenceState.java:42)
        at 
com.ibm.ws.webcontainer.servlet.ServletInstanceReference.dispatch(ServletInstanceReference.java:40)
        at 
com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.handleWebAppDispatch(WebAppRequestDispatcher.java:1019)
        at 
com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.dispatch(WebAppRequestDispatcher.java:592)
        at 
com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java:204)
        at 
com.ibm.ws.webcontainer.srt.WebAppInvoker.doForward(WebAppInvoker.java:125)
        at 
com.ibm.ws.webcontainer.srt.WebAppInvoker.handleInvocationHook(WebAppInvoker.java:286)
        at 
com.ibm.ws.webcontainer.cache.invocation.CachedInvocation.handleInvocation(CachedInvocation.java:71)
        at 
com.ibm.ws.webcontainer.cache.invocation.CacheableInvocationContext.invoke(CacheableInvocationContext.java:116)
        at 
com.ibm.ws.webcontainer.srp.ServletRequestProcessor.dispatchByURI(ServletRequestProcessor.java:186)
        at 
com.ibm.ws.webcontainer.oselistener.OSEListenerDispatcher.service(OSEListener.java:334)
        at 
com.ibm.ws.webcontainer.http.HttpConnection.handleRequest(HttpConnection.java:56)
        at 
com.ibm.ws.http.HttpConnection.readAndHandleRequest(HttpConnection.java:615)
        at com.ibm.ws.http.HttpConnection.run(HttpConnection.java:439)
        at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:912)

On my opinion this is quite serious problem since SOAP service cannot trust 
that client always sends valid SOAP request.
Shouldn't XFire notice that type defined in request is not defined in WSDL or 
XMLSchema and return SOAP Fault?

Is there any quick workaround to prevent this happening assuming that I don't 
have time to implement my SOAP service from scratch using different approach?


-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply via email to