XFire
  1. XFire
  2. XFIRE-533

java.lang.ArrayIndexOutOfBoundsException when marshalling byte array

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Blocker 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 :
      0

      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)

        Activity

        Hide
        Bruce Li added a comment -

        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];
        for (int sourceStart = 0;; sourceStart += length)

        { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied < length) break; }
        ...
        }

        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];
        // for (int sourceStart = 0;; sourceStart += length)
        //

        { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); // if (nCopied < length) // break; //}

        ...
        }

        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];
        for (int sourceStart = 0;; sourceStart += length)

        { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied <= length) // Change "<" to "<=" break; }

        ...
        }

        Show
        Bruce Li added a comment - 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] ; for (int sourceStart = 0;; sourceStart += length) { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied < length) break; } ... } 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] ; // for (int sourceStart = 0;; sourceStart += length) // { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); // if (nCopied < length) // break; //} ... } 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] ; for (int sourceStart = 0;; sourceStart += length) { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied <= length) // Change "<" to "<=" break; } ... }
        Hide
        Christoph Sturm added a comment -

        from the stacktrace it looks like you are using the stax reference implementation. could you try if it works if you use woodstox instead?

        Show
        Christoph Sturm added a comment - from the stacktrace it looks like you are using the stax reference implementation. could you try if it works if you use woodstox instead?
        Hide
        Christoph Sturm added a comment -

        disregard my last comment, which i wrote while you wrote yours

        thanks for looking into this, do you have a testcase too maybe?

        Show
        Christoph Sturm added a comment - disregard my last comment, which i wrote while you wrote yours thanks for looking into this, do you have a testcase too maybe?
        Hide
        Bruce Li added a comment -

        It's my pleasure.
        I have to copy/paste again since the "/n" is gone.

        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];

        // for (int sourceStart = 0;; sourceStart += length)

        //

        { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); // if (nCopied < length) // break; //}

        ...
        }

        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];

        for (int sourceStart = 0;; sourceStart += length)

        { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied <= length) // Change "<" to "<=" break; }

        ...

        }

        Show
        Bruce Li added a comment - It's my pleasure. I have to copy/paste again since the "/n" is gone. 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] ; // for (int sourceStart = 0;; sourceStart += length) // { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); // if (nCopied < length) // break; //} ... } 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] ; for (int sourceStart = 0;; sourceStart += length) { int nCopied = reader.getTextCharacters(sourceStart, myBuffer, 0, length); Base64.decode(myBuffer, 0, nCopied, bos); if (nCopied <= length) // Change "<" to "<=" break; } ... }
        Hide
        Bruce Li added a comment -

        I have the fake test case as following:

        .NET platform (C# Client)

        {
        ...
        RemoteAdapter.JddServiceWsAdapter jddAdapter = new RemoteJddAdapter.JddServiceWsAdapter();
        zipName = "D:\\Test
        MyTarget.zip";
        zipBytes = getData(zipName, 204800);

        try

        { string tasks = jddAdapter.doTask(zipName,zipBytes,...) }

        catch(Exception e)

        { MessageBox.Show( "JDD Adapter exception thrown: " + e.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; }

        ...

        Java Platform (Server):

        public String doTask(String zipName,byte[] zipBytes,...)

        { ... }

        The web server security uses "aegis"

        Show
        Bruce Li added a comment - I have the fake test case as following: .NET platform (C# Client) { ... RemoteAdapter.JddServiceWsAdapter jddAdapter = new RemoteJddAdapter.JddServiceWsAdapter(); zipName = "D:\\Test MyTarget.zip"; zipBytes = getData(zipName, 204800); try { string tasks = jddAdapter.doTask(zipName,zipBytes,...) } catch(Exception e) { MessageBox.Show( "JDD Adapter exception thrown: " + e.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } ... Java Platform (Server): public String doTask(String zipName,byte[] zipBytes,...) { ... } The web server security uses "aegis"
        Hide
        Bruce Li added a comment -

        Which is official way to contribute my fix?

        Show
        Bruce Li added a comment - Which is official way to contribute my fix?

          People

          • Assignee:
            Dan Diephouse
            Reporter:
            Bruce Li
          • Votes:
            2 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated: