Skip to content

Commit 361903b

Browse files
committed
Fix PUBLISH DUP Initial-Send and QoS0 Constraint Is Not Enforced by the Generic Encoder
1 parent d9b0aa3 commit 361903b

2 files changed

Lines changed: 77 additions & 0 deletions

File tree

src/mqtt_packet.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,13 @@ int MqttEncode_Publish(byte *tx_buf, int tx_buf_len, MqttPublish *publish,
15141514
}
15151515
variable_len += MQTT_DATA_LEN_SIZE; /* For packet_id */
15161516
}
1517+
else if (publish->duplicate) {
1518+
/* [MQTT-3.3.1-2] DUP MUST be 0 for all QoS 0 PUBLISH messages.
1519+
* The decoder rejects this combination via MqttPacket_FixedHeader
1520+
* FlagsValid; mirror the constraint at the encoder boundary so the
1521+
* library never produces a forbidden wire packet for a caller. */
1522+
return MQTT_TRACE_ERROR(MQTT_CODE_ERROR_BAD_ARG);
1523+
}
15171524

15181525
#ifdef WOLFMQTT_V5
15191526
if (publish->protocol_level >= MQTT_CONNECT_PROTOCOL_LEVEL_5) {

tests/test_mqtt_packet.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,73 @@ TEST(encode_publish_qos0_no_flags_in_header)
794794
ASSERT_EQ(0, (int)MQTT_PACKET_FLAGS_GET(tx_buf[0]));
795795
}
796796

797+
/* [MQTT-3.3.1-2] DUP MUST be 0 for all QoS 0 messages. The encoder must
798+
* refuse the forbidden combination at the API boundary so the library can't
799+
* produce a wire packet that the decoder (and any spec-compliant receiver)
800+
* would reject as malformed. */
801+
TEST(encode_publish_qos0_with_dup_rejected)
802+
{
803+
byte tx_buf[64];
804+
byte payload[] = { 'x' };
805+
MqttPublish pub;
806+
int rc;
807+
808+
XMEMSET(&pub, 0, sizeof(pub));
809+
pub.topic_name = "a";
810+
pub.qos = MQTT_QOS_0;
811+
pub.duplicate = 1;
812+
pub.buffer = payload;
813+
pub.total_len = sizeof(payload);
814+
815+
rc = MqttEncode_Publish(tx_buf, (int)sizeof(tx_buf), &pub, 0);
816+
ASSERT_EQ(MQTT_CODE_ERROR_BAD_ARG, rc);
817+
}
818+
819+
/* QoS 1 with DUP=1 is a legitimate retransmission shape per [MQTT-4.3.2].
820+
* Pin that the new check is QoS-0-specific and doesn't break retransmits. */
821+
TEST(encode_publish_qos1_with_dup_accepted)
822+
{
823+
byte tx_buf[64];
824+
byte payload[] = { 'x' };
825+
MqttPublish pub;
826+
int rc;
827+
828+
XMEMSET(&pub, 0, sizeof(pub));
829+
pub.topic_name = "a";
830+
pub.qos = MQTT_QOS_1;
831+
pub.packet_id = 42;
832+
pub.duplicate = 1;
833+
pub.buffer = payload;
834+
pub.total_len = sizeof(payload);
835+
836+
rc = MqttEncode_Publish(tx_buf, (int)sizeof(tx_buf), &pub, 0);
837+
ASSERT_TRUE(rc > 0);
838+
/* Fixed-header low nibble: DUP|QoS1 = 0x8 | 0x2 = 0xA. */
839+
ASSERT_EQ(0xA, (int)MQTT_PACKET_FLAGS_GET(tx_buf[0]));
840+
}
841+
842+
/* QoS 2 with DUP=1 is also a legitimate retransmission shape per [MQTT-4.3.3]. */
843+
TEST(encode_publish_qos2_with_dup_accepted)
844+
{
845+
byte tx_buf[64];
846+
byte payload[] = { 'x' };
847+
MqttPublish pub;
848+
int rc;
849+
850+
XMEMSET(&pub, 0, sizeof(pub));
851+
pub.topic_name = "a";
852+
pub.qos = MQTT_QOS_2;
853+
pub.packet_id = 42;
854+
pub.duplicate = 1;
855+
pub.buffer = payload;
856+
pub.total_len = sizeof(payload);
857+
858+
rc = MqttEncode_Publish(tx_buf, (int)sizeof(tx_buf), &pub, 0);
859+
ASSERT_TRUE(rc > 0);
860+
/* DUP|QoS2 = 0x8 | 0x4 = 0xC. */
861+
ASSERT_EQ(0xC, (int)MQTT_PACKET_FLAGS_GET(tx_buf[0]));
862+
}
863+
797864
/* f-2360: topic_name with strlen > 65535 must not produce a "successful"
798865
* encode. MqttEncode_String returns -1 for oversize strings; the encoder
799866
* must surface that as a negative return rather than adding -1 to the
@@ -2783,6 +2850,9 @@ void run_mqtt_packet_tests(void)
27832850
RUN_TEST(encode_publish_qos1_retain_flags_in_header);
27842851
RUN_TEST(encode_publish_qos2_duplicate_flags_in_header);
27852852
RUN_TEST(encode_publish_qos0_no_flags_in_header);
2853+
RUN_TEST(encode_publish_qos0_with_dup_rejected);
2854+
RUN_TEST(encode_publish_qos1_with_dup_accepted);
2855+
RUN_TEST(encode_publish_qos2_with_dup_accepted);
27862856
RUN_TEST(encode_publish_topic_oversized_rejected);
27872857

27882858
/* MqttDecode_Publish */

0 commit comments

Comments
 (0)