Skip to content

Fix duplicate 10= checksum when resending a message ending in a repeating group#767

Open
raphaelroshan wants to merge 1 commit into
quickfixgo:mainfrom
raphaelroshan:fix/resend-group-duplicate-checksum
Open

Fix duplicate 10= checksum when resending a message ending in a repeating group#767
raphaelroshan wants to merge 1 commit into
quickfixgo:mainfrom
raphaelroshan:fix/resend-group-duplicate-checksum

Conversation

@raphaelroshan

Copy link
Copy Markdown

Fixes #761.

Problem

When a stored outbound message whose body ends in a repeating group is parsed with a DataDictionary (the resend path always uses one), parseGroup leaks the 10= trailer into Message.bodyBytes. On resend, buildWithBodyBytes writes that contaminated bodyBytes and appends a freshly computed 10= on top — producing two 10= tags and a wrong BodyLength. The counterparty rejects with Invalid checksum and drops the session.

All three conditions are required: a DataDictionary is configured, the body contains a repeating group, and the counterparty sends a ResendRequest.

Root cause

parseGroup's loop sets mp.trailerBytes = mp.rawBytes after extractField consumes each field. When it consumes the trailer field (10=NNN), rawBytes is empty, so trailerBytes = "". The caller's strip

if len(mp.msg.bodyBytes) > len(mp.trailerBytes) {
    mp.msg.bodyBytes = mp.msg.bodyBytes[:len(mp.msg.bodyBytes)-len(mp.trailerBytes)]
}

then removes zero bytes, leaving the trailer embedded. The non-group default path is unaffected because it sets trailerBytes while rawBytes still includes the upcoming trailer.

Fix

parseGroup snapshots the pre-extract buffer and, on detecting the trailer field, restores trailerBytes to it (the buffer that still holds 10=NNN), so the strip removes the trailer exactly as the non-group path does.

Test

Added TestReBuildWithRepeatingGroupWithDictionaryForResend: parses a message ending in a 453 group with a FIX44 dictionary and asserts (a) bodyBytes no longer contains the trailer and (b) the resend built from bodyBytes carries exactly one 10=. Fails before, passes after. Existing tests and the full package suite pass.

… group

When a stored message whose body ends in a repeating group is parsed with a
DataDictionary, parseGroup set trailerBytes to the (now-empty) rawBytes after
consuming the trailer field, so the caller's bodyBytes strip removed nothing
and left the 10= trailer embedded in bodyBytes. On resend, buildWithBodyBytes
wrote that contaminated bodyBytes and appended a fresh 10=, producing two
checksum tags and a wrong BodyLength, which the counterparty rejects.

parseGroup now restores the pre-extract buffer (which still holds the trailer)
when it detects the trailer field, so the strip removes it as in the non-group
path. Adds a dictionary-based resend test covering a body that ends in a group.
@raphaelroshan raphaelroshan marked this pull request as ready for review July 15, 2026 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resend of message with repeating group emits two 10= checksum tags (parseGroup leaks trailer into bodyBytes)

1 participant