Details
-
Type:
Bug
-
Status:
Open
-
Priority:
Blocker
-
Resolution: Unresolved
-
Affects Version/s: 1.1.2
-
Fix Version/s: None
-
Component/s: Core
-
Labels:None
-
Environment:JDK 1.5 and Tomcat 5.5.15
-
Number of attachments :
Description
The "java.lang.ArrayIndexOutOfBoundsException" is thrown when the byte array parameter is passed from .Net platform to Java platform.
There is no such error in version 1.0 (xfire-all-1.0.jar) but happen in version 1.1 (xfire-all-1.1.jar and xfire-all-1.1.2.jar)
The following is the dump:
java.lang.ArrayIndexOutOfBoundsException
at com.bea.xml.stream.MXParser.getTextCharacters(MXParser.java:1450)
at org.codehaus.xfire.util.stax.DepthXMLStreamReader.getTextCharacters(DepthXMLStreamReader.java:179)
at org.codehaus.xfire.util.stax.DepthXMLStreamReader.getTextCharacters(DepthXMLStreamReader.java:179)
at org.codehaus.xfire.aegis.type.basic.Base64Type.readObject(Base64Type.java:71)
at org.codehaus.xfire.aegis.AegisBindingProvider.readParameter(AegisBindingProvider.java:94)
at org.codehaus.xfire.service.binding.AbstractBinding.read(AbstractBinding.java:208)
at org.codehaus.xfire.service.binding.WrappedBinding.readMessage(WrappedBinding.java:50)
at org.codehaus.xfire.soap.handler.SoapBodyHandler.invoke(SoapBodyHandler.java:42)
at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:110)
at org.codehaus.xfire.transport.DefaultEndpoint.onReceive(DefaultEndpoint.java:61)
at org.codehaus.xfire.transport.AbstractChannel.receive(AbstractChannel.java:38)
at org.codehaus.xfire.transport.http.XFireServletController.invoke(XFireServletController.java:261)
at org.codehaus.xfire.transport.http.XFireServletController.doService(XFireServletController.java:120)
at org.codehaus.xfire.spring.remoting.XFireServletControllerAdapter.handleRequest(XFireServletControllerAdapter.java:63)
at org.codehaus.xfire.spring.remoting.XFireExporter.handleRequest(XFireExporter.java:44)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:45)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:798)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:728)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:396)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:360)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:667)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:595)
To debug Xfire with source code of version 1.1.2, the problem happens when marshalling byte array. The following is the segment of source code from org.codehaus.xfire.aegis.type.basic.Base64Type that causes exception:
Xfire v1.1.2: org.codehaus.xfire.aegis.type.basic.Base64Type
public Object readObject(MessageReader mreader, MessageContext context)
throws XfireFault
{
...
int length = reader.getTextLength();
char[] myBuffer = new char[length];
{ int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied < length) break; }for (int sourceStart = 0;; sourceStart += length)
...
}
When debug, the length is the byte array size after the call of "reader.getTextLength()". And then, "nCopied" equal "length" after "getTextCharacters" call.
if (nCopied < length) // Wrong!!! (nCopied == length) and it should break
break;
Because of above comparison expression, it goes to the next loop, it definitely throw "java.lang.ArrayIndexOutOfBoundsException" running at "reader.getTextCharacters(sourceStart, myBuffer, 0, length)"
Comparing the segment code of Xfire v1.0, it doesn't have such bug as following:
Xfire v1.0: org.codehaus.xfire.aegis.type.basic.Base64Type
public Object readObject(MessageReader mreader, MessageContext context)
throws XfireFault
{
...
int length = 1024;
char[] myBuffer = new char[length];
for (int sourceStart = 0;; sourceStart += length)
{ int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied < length) break; }
...
}
Obviously, the logic of the segment of code is changed from v1.0 to v1.1. I could fix it as following:
public Object readObject(MessageReader mreader, MessageContext context)
throws XfireFault
{
...
int length = reader.getTextLength();
char[] myBuffer = new char[length];
{ int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); // if (nCopied < length) // break; //}// for (int sourceStart = 0;; sourceStart += length)
//
...
}
However, I finally just fix it as following for temporary use:
public Object readObject(MessageReader mreader, MessageContext context)
throws XfireFault
{
...
int length = reader.getTextLength();
char[] myBuffer = new char[length];
{ int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied <= length) // Change "<" to "<=" break; }for (int sourceStart = 0;; sourceStart += length)
...
}