Skip to content

Fix inbound command payload truncation at 1000 wide chars in connector DLLs#308

Open
biohazardxxx wants to merge 4 commits into
vdemydiuk:devfrom
biohazardxxx:fix/connector-payload-truncation
Open

Fix inbound command payload truncation at 1000 wide chars in connector DLLs#308
biohazardxxx wants to merge 4 commits into
vdemydiuk:devfrom
biohazardxxx:fix/connector-payload-truncation

Conversation

@biohazardxxx

Copy link
Copy Markdown

Summary

Inbound command payloads (client → EA) were silently truncated at 1000 wide characters by convertSystemString in both connector DLLs, even though the experts allocate a 5000-character payload buffer (StringInit(payload, 5000, 0)). Any command whose JSON payload exceeded 1000 characters arrived cut off mid-JSON, failed parsing in the EA and surfaced as Failed to get payload — an error that looks like a transport bug. The helper also never wrote a null terminator, so a shorter error message written into a reused _error buffer could leak the tail of a previous, longer one.

This PR removes the cap entirely:

  • convertSystemString(dest, src, capacity) now receives the destination capacity, bounds the copy and always null-terminates.
  • getPayload keeps its signature (old EAs keep working) but honors the expert's real 5000-character buffer instead of 1000.
  • New size-aware export in both DLLs:
    // returns the full payload length in wchar_t (excluding null), or -1 on error;
    // copies at most capacity-1 chars and always null-terminates
    int getPayload2(int expertHandle, wchar_t* res, int capacity, wchar_t* err);
  • GetJsonPayload in both experts (MQL4 + MQL5) fetches via getPayload2 with the default 5000-character buffer and, when the reported size is larger, re-allocates to the exact size and fetches again — one connector round-trip in the common case, two for oversized payloads.

Implementation notes

  • Re-reading the payload is safe: MtExpert::GetCommandPayload() reads current_task_ non-destructively; the task is only consumed on SendResponse.
  • MtCommand/WebSocket transport already handle arbitrary payload sizes — the cap was exclusively in this one copy helper.
  • Applies identically to MT5Connector and MTConnector; recompiled MtApi5.ex5 and MtApi.ex4 are included.
  • Old EA + new DLL remains compatible (old getPayload path, now capped at 4999 instead of 1000). New EA requires the new DLL (imports getPayload2); DLL and expert ship together in the installer.

Testing

  • MT5Connector (x64) and MTConnector (Win32) build clean in Release; MtApi5.mq5 and MtApi.mq4 compile with Result: 0 errors, 0 warnings.
  • Runtime-verified against a live MT5 terminal (build 5830) with the new DLL deployed and the recompiled EA attached:
    • Print with a 6015-character message (payload above even the 5000 default buffer, exercising the re-allocate path): returns true, EA parses and executes the command.
    • Control on the same terminal, same DLL, but an expert running the old .ex5: the same 6015-character command fails with Failed to get payload — reproducing the original defect and confirming the fix is what makes the difference.
    • Short-payload sanity command on the new stack: unchanged behavior.
  • MQL4 expert change is source-identical to the MQL5 one and compiles clean, but was not runtime-tested against an MT4 terminal.

Removes the payload-size caveat documented in #307 (struct-array commands no longer need client-side chunking once both land).

🤖 Generated with Claude Code

biohazardxxx and others added 4 commits July 6, 2026 12:33
convertSystemString copied at most 1000 wchars into the caller's MQL
string buffer regardless of its actual capacity and never wrote a null
terminator (stale content from a previous, longer error message could
leak into reused buffers). Command payloads longer than 1000 characters
arrived truncated in the EA and failed JSON parsing.

- convertSystemString now takes the destination capacity, bounds the
  copy and always null-terminates.
- getPayload keeps its signature but honors the EA's real 5000-wchar
  payload buffer (StringInit(payload, 5000, 0)) instead of 1000.
- New size-aware export getPayload2(handle, res, capacity, err) returns
  the full payload length (or -1 on error) and copies at most
  capacity-1 chars, so callers can re-allocate and fetch payloads of
  any size.

Applies to both MT5Connector and MTConnector.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GetJsonPayload now asks the connector for the payload with an explicit
buffer capacity and re-allocates when the reported size exceeds the
default 5000-character buffer, removing the previous hard cap on
inbound command payloads.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Same change as the MQL5 expert: GetJsonPayload re-allocates its buffer
based on the size reported by getPayload2, removing the inbound payload
cap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant