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