Skip to content

Commit 81bf713

Browse files
committed
Fix request length check in modbus_reply in RTU
- rename internal *_prepare_response_tid to *_get_response_tid - change signature, don't need req length anymore - remove misleading modification of req_length - check of req length before use in memcpy for mask write register Related to df79a02
1 parent 65dd08c commit 81bf713

File tree

4 files changed

+52
-32
lines changed

4 files changed

+52
-32
lines changed

src/modbus-private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ typedef struct _modbus_backend {
7575
int (*build_request_basis)(
7676
modbus_t *ctx, int function, int addr, int nb, uint8_t *req);
7777
int (*build_response_basis)(sft_t *sft, uint8_t *rsp);
78-
int (*prepare_response_tid)(const uint8_t *req, int *req_length);
78+
int (*get_response_tid)(const uint8_t *req);
7979
int (*send_msg_pre)(uint8_t *req, int req_length);
8080
ssize_t (*send)(modbus_t *ctx, const uint8_t *req, int req_length);
8181
int (*receive)(modbus_t *ctx, uint8_t *req);

src/modbus-rtu.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,8 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
129129
return (crc_hi << 8 | crc_lo);
130130
}
131131

132-
static int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length)
132+
static int _modbus_rtu_get_response_tid(const uint8_t *req)
133133
{
134-
(*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH;
135134
/* No TID */
136135
return 0;
137136
}
@@ -1187,7 +1186,7 @@ const modbus_backend_t _modbus_rtu_backend = {
11871186
_modbus_set_slave,
11881187
_modbus_rtu_build_request_basis,
11891188
_modbus_rtu_build_response_basis,
1190-
_modbus_rtu_prepare_response_tid,
1189+
_modbus_rtu_get_response_tid,
11911190
_modbus_rtu_send_msg_pre,
11921191
_modbus_rtu_send,
11931192
_modbus_rtu_receive,

src/modbus-tcp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ static int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp)
153153
return _MODBUS_TCP_PRESET_RSP_LENGTH;
154154
}
155155

156-
static int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
156+
static int _modbus_tcp_get_response_tid(const uint8_t *req)
157157
{
158158
return (req[0] << 8) + req[1];
159159
}
@@ -838,7 +838,7 @@ const modbus_backend_t _modbus_tcp_backend = {
838838
_modbus_set_slave,
839839
_modbus_tcp_build_request_basis,
840840
_modbus_tcp_build_response_basis,
841-
_modbus_tcp_prepare_response_tid,
841+
_modbus_tcp_get_response_tid,
842842
_modbus_tcp_send_msg_pre,
843843
_modbus_tcp_send,
844844
_modbus_tcp_receive,
@@ -861,7 +861,7 @@ const modbus_backend_t _modbus_tcp_pi_backend = {
861861
_modbus_set_slave,
862862
_modbus_tcp_build_request_basis,
863863
_modbus_tcp_build_response_basis,
864-
_modbus_tcp_prepare_response_tid,
864+
_modbus_tcp_get_response_tid,
865865
_modbus_tcp_send_msg_pre,
866866
_modbus_tcp_send,
867867
_modbus_tcp_receive,

src/modbus.c

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ int modbus_flush(modbus_t *ctx)
125125
return rc;
126126
}
127127

128-
/* Computes the length of the expected response */
128+
/* Computes the length of the expected response including checksum */
129129
static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t *req)
130130
{
131131
int length;
@@ -394,8 +394,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
394394
length_to_read = ctx->backend->header_length + 1;
395395

396396
if (msg_type == MSG_INDICATION) {
397-
/* Wait for a message, we don't know when the message will be
398-
* received */
397+
/* Wait for a message, we don't know when the message will be received */
399398
if (ctx->indication_timeout.tv_sec == 0 && ctx->indication_timeout.tv_usec == 0) {
400399
/* By default, the indication timeout isn't set */
401400
p_tv = NULL;
@@ -805,7 +804,7 @@ int modbus_reply(modbus_t *ctx,
805804

806805
sft.slave = slave;
807806
sft.function = function;
808-
sft.t_id = ctx->backend->prepare_response_tid(req, &req_length);
807+
sft.t_id = ctx->backend->get_response_tid(req);
809808

810809
/* Data are flushed on illegal number of values errors. */
811810
switch (function) {
@@ -901,7 +900,7 @@ int modbus_reply(modbus_t *ctx,
901900
MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
902901
rsp,
903902
FALSE,
904-
"Illegal data address 0x%0X in write_bit\n",
903+
"Illegal data address 0x%0X in write bit\n",
905904
address);
906905
break;
907906
}
@@ -910,20 +909,26 @@ int modbus_reply(modbus_t *ctx,
910909
rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
911910
if (rsp_length != req_length) {
912911
/* Bad use of modbus_reply */
913-
rsp_length =
914-
response_exception(ctx,
915-
&sft,
916-
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
917-
rsp,
918-
FALSE,
919-
"Invalid request length used in modbus_reply (%d)\n",
920-
req_length);
912+
rsp_length = response_exception(
913+
ctx,
914+
&sft,
915+
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
916+
rsp,
917+
FALSE,
918+
"Invalid request length in modbus_reply to write bit (%d)\n",
919+
req_length);
921920
break;
922921
}
923922

923+
/* Don't copy the CRC, if any, it will be computed later (even if identical to the
924+
* request) */
925+
rsp_length -= ctx->backend->checksum_length;
926+
924927
int data = (req[offset + 3] << 8) + req[offset + 4];
925928
if (data == 0xFF00 || data == 0x0) {
929+
/* Apply the change to mapping */
926930
mb_mapping->tab_bits[mapping_address] = data ? ON : OFF;
931+
/* Prepare response */
927932
memcpy(rsp, req, rsp_length);
928933
} else {
929934
rsp_length = response_exception(
@@ -955,19 +960,21 @@ int modbus_reply(modbus_t *ctx,
955960
rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
956961
if (rsp_length != req_length) {
957962
/* Bad use of modbus_reply */
958-
rsp_length =
959-
response_exception(ctx,
960-
&sft,
961-
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
962-
rsp,
963-
FALSE,
964-
"Invalid request length used in modbus_reply (%d)\n",
965-
req_length);
963+
rsp_length = response_exception(
964+
ctx,
965+
&sft,
966+
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
967+
rsp,
968+
FALSE,
969+
"Invalid request length in modbus_reply to write register (%d)\n",
970+
req_length);
966971
break;
967972
}
968973
int data = (req[offset + 3] << 8) + req[offset + 4];
969974

970975
mb_mapping->tab_registers[mapping_address] = data;
976+
977+
rsp_length -= ctx->backend->checksum_length;
971978
memcpy(rsp, req, rsp_length);
972979
} break;
973980
case MODBUS_FC_WRITE_MULTIPLE_COILS: {
@@ -1088,8 +1095,23 @@ int modbus_reply(modbus_t *ctx,
10881095

10891096
data = (data & and) | (or &(~and) );
10901097
mb_mapping->tab_registers[mapping_address] = data;
1091-
memcpy(rsp, req, req_length);
1092-
rsp_length = req_length;
1098+
1099+
rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
1100+
if (rsp_length != req_length) {
1101+
/* Bad use of modbus_reply */
1102+
rsp_length = response_exception(ctx,
1103+
&sft,
1104+
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
1105+
rsp,
1106+
FALSE,
1107+
"Invalid request length in modbus_reply "
1108+
"to mask write register (%d)\n",
1109+
req_length);
1110+
break;
1111+
}
1112+
1113+
rsp_length -= ctx->backend->checksum_length;
1114+
memcpy(rsp, req, rsp_length);
10931115
}
10941116
} break;
10951117
case MODBUS_FC_WRITE_AND_READ_REGISTERS: {
@@ -1177,7 +1199,6 @@ int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int excep
11771199
int function;
11781200
uint8_t rsp[MAX_MESSAGE_LENGTH];
11791201
int rsp_length;
1180-
int dummy_length = 99;
11811202
sft_t sft;
11821203

11831204
if (ctx == NULL) {
@@ -1191,7 +1212,7 @@ int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int excep
11911212

11921213
sft.slave = slave;
11931214
sft.function = function + 0x80;
1194-
sft.t_id = ctx->backend->prepare_response_tid(req, &dummy_length);
1215+
sft.t_id = ctx->backend->get_response_tid(req);
11951216
rsp_length = ctx->backend->build_response_basis(&sft, rsp);
11961217

11971218
/* Positive exception code */

0 commit comments

Comments
 (0)