Uploaded image for project: 'QuickFIX/J'
  1. QuickFIX/J
  2. QFJ-544

Header with BeginString=FIXT.1.1 incorrectly parsed by FIXMessageDecoder (manifests as missing messages)

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Default
    • Resolution: Fixed
    • Affects Version/s: 1.4.0
    • Fix Version/s: 1.5.3
    • Component/s: Engine
    • Labels:
      None

      Description

      When BeginString=FIXT.1.1 messages can be skipped if the buffer ends before the last '=' of "8=FIXT.1.1\0019=". That will happen if the buffer contains a correct message before that.

      Example:

      in messages:

      8=FIXT.1.1\0019=12\00135=X\001108=30\00110=036\0018=FIXT.1.1\0019=12\00135=X\001108=30\00110=036\001

      the second message will fail to be decoded if the buffer contents presented to the FixMessageDecoder in two subsequent decode() invocations are:

      "8=FIXT.1.1\0019=12\00135=X\001108=30\00110=036\0018=FIXT.1.1\0019"

      and

      "=12\00135=X\001108=30\00110=036\001"

      I have created tests to replicate this issue (and also issue QFJ-505) and included fixes (for this and the fix proposed in QFJ-505).
      Here is the diff:

      Index: core/src/test/java/quickfix/mina/message/FIXMessageDecoderTest.java
      ===================================================================
      — core/src/test/java/quickfix/mina/message/FIXMessageDecoderTest.java (revision 46)
      +++ core/src/test/java/quickfix/mina/message/FIXMessageDecoderTest.java (revision 49)
      @@ -348,7 +348,22 @@

      @Test
      public void testMinaDemux() throws Exception

      { - DemuxingProtocolCodecFactory codecFactory = new DemuxingProtocolCodecFactory(); + String message = "8=FIX.4.2\0019=12\00135=X\001108=30\00110=036\001"; + + doTestMinaDemux(message); + + }

      +
      + @Test
      + public void testMinaDemuxFixt() throws Exception

      { + String message = "8=FIXT.1.1\0019=12\00135=X\001108=30\00110=036\001"; + + doTestMinaDemux(message); + + }

      +
      + private void doTestMinaDemux(String message) throws Exception, UnsupportedEncodingException {
      + DemuxingProtocolCodecFactory codecFactory = new DemuxingProtocolCodecFactory();
      codecFactory.register(FIXMessageDecoder.class);

      ProtocolDecoder decoder = codecFactory.getDecoder();
      @@ -359,7 +374,7 @@
      int count = 5;
      String data = "";
      for (int i = 0; i < count; i++)

      { - data += "8=FIX.4.2\0019=12\00135=X\001108=30\00110=036\001"; + data += message; }

      for (int i = 1; i < data.length(); i++)

      { @@ -379,9 +394,8 @@ output.reset(); buffer.clear(); }

      -

      • }
        -
        + }
        +
        private void assertMessageFound(String data) throws ProtocolCodecException { assertMessageFound(data, 1); }

        Index: core/src/main/java/quickfix/mina/message/FIXMessageDecoder.java
        ===================================================================

          • core/src/main/java/quickfix/mina/message/FIXMessageDecoder.java (revision 46)
            +++ core/src/main/java/quickfix/mina/message/FIXMessageDecoder.java (revision 49)
            @@ -123,7 +123,7 @@
            }
            if (messageCount > 0) {
            // Mina will compact the buffer because we can't detect a header
      • if (in.remaining() < minMaskLength(HEADER_PATTERN))
        Unknown macro: {+ if (state == SEEKING_HEADER) { position = 0; } return MessageDecoderResult.OK;@@ -297,7 +297,8 @@ }

      private static BufPos indexOf(ByteBuffer buffer, int position, byte[] data) {

      • for (int offset = position, limit = buffer.limit() - minMaskLength(data) + 1; offset < limit; offset++) {
        + int limit = buffer.limit() - minMaskLength(data) + 1;
        + for (int offset = position ; offset < limit; offset++)
        Unknown macro: { int length; if (buffer.get(offset) == data[0] && (length = startsWith(buffer, offset, data)) > 0) { return new BufPos(offset, length); @@ -337,6 +338,10 @@ return -1; } }

        + if(dataOffset != data.length)

        { + // when minMaskLength(data) != data.length we might run out of buffer before we run out of data + return -1; + }

        return bufferOffset - initOffset;
        }

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                chrjohn Christoph John
                Reporter:
                stelios.papadopoulos Stelios Papadopoulos
              • Votes:
                3 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: