Stop outbound drain when Session hand-off takes its queue. Claim Will before publishing it. Do not report a successful cancel while a reader owns the request. Take the client lock over the Session replay pool in MqttClient_Connect. - #622
kareem-wolfssl wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Build failure, replay races, non-terminating cancellation, and duplicate QoS 0 delivery remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 3
Open (4)
What changed in this PR
Hardens MQTT client and broker state ownership during concurrent cancellation, session replay, queue hand-off, and Will publication.
Changes:
- Adds synchronization and cancellation ownership safeguards.
- Prevents broker queue and Will reuse during re-entrant callbacks.
- Adds regression tests and allocator instrumentation.
| File | Description |
|---|---|
wolfmqtt/mqtt_client.h |
Documents cancellation ownership semantics. |
src/mqtt_client.c |
Synchronizes replay state and pending-response cancellation. |
src/mqtt_broker.c |
Handles re-entrant queue transfer and Will publication. |
tests/test_mqtt_client.c |
Tests replay locking and cancellation. |
tests/test_broker_connect.c |
Tests queue hand-off and Will re-entry. |
tests/include.am |
Injects allocator hooks into unit tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
embhorn
left a comment
There was a problem hiding this comment.
Review skoll comments and failing tests
…kes its queue. Thanks to Gwanhyun Lee for the report.
Thanks to Gwanhyun Lee for the report.
…s the request. Thanks to Gwanhyun Lee for the report.
… MqttClient_Connect. Thanks to Gwanhyun Lee for the report.
3908b69 to
ef23354
Compare
| if (client->replay[i].packet_id != 0 && | ||
| MqttClient_SendIds_Find(client, | ||
| client->replay[i].packet_id) >= 0) { | ||
| continue; /* published on this connection */ |
| (void)MqttClient_SendIdReserve_Locked(client, | ||
| client->replay[i].packet_id, &client->replay[i], 1, | ||
| client->replay[i].pubrelSent ? | ||
| MQTT_PACKET_TYPE_PUBLISH_COMP : | ||
| ((client->replay[i].qos == MQTT_QOS_2) ? | ||
| MQTT_PACKET_TYPE_PUBLISH_COMP : | ||
| MQTT_PACKET_TYPE_PUBLISH_ACK)); |
| if (cur->qos != MQTT_QOS_0) { | ||
| cur->retransmit_dup = 1; | ||
| return; | ||
| } |
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #622
Scan targets checked: wolfmqtt-src, wolfmqtt-bugs
Coverage: 2 of 5 in-scope changed file(s) opened by the reviewer; not opened: tests/test_broker_connect.c, tests/test_mqtt_client.c, wolfmqtt/mqtt_client.h
Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Reported findings require changes before merge.
Review tier: Lite
| tmpResp->packet_type, tmpResp->packet_id, | ||
| tmpResp->packetProcessing, tmpResp->packetDone); | ||
| #endif | ||
| if (tmpResp->packetProcessing && !tmpResp->packetDone) { |
There was a problem hiding this comment.
New CONTINUE return from CancelMessage is ignored by internal error paths, leaving a stale pendResp linked · API contract violations
MqttClient_CancelMessage can now return MQTT_CODE_CONTINUE without unlinking the pendResp or resetting stat. The failure paths in Publish (4247, 4294), Subscribe (4543), Unsubscribe (4698), Ping (4862) and Connect (3457) ignore that return and report the error anyway. The caller can then free or reuse an object that is still on firstPendResp, which leaves a dangling list node.
Suggested fix: Update every internal caller of MqttClient_CancelMessage to handle MQTT_CODE_CONTINUE. Either wait until the reader sets packetDone and cancel again, or keep the object owned instead of returning an error.
Related known findings (similar but distinct; listed for context, not part of this finding)
- F-13261 (open): File/function: same function MqttClient_CancelMessage as F-13261. Operation: F-13261 is the active-read release path omitting an rx_buf scrub; candidate is the packetProcessing-and-not-done early return skipping RespList_Remove when callers ignore MQTT_CODE_CONTINUE. Root cause: F-13261 is missing buffer zeroization (info disclosure); candidate is a missing caller-side contract check leaving a stale linked-list node (dangling pointer / potential use-after-free). Patch: one requires clearing rx_buf


No description provided.