Skip to content

Commit d8a971e

Browse files
committed
Check length passed to modbus_reply (write_register)
Related to df79a02.
1 parent df79a02 commit d8a971e

File tree

3 files changed

+42
-15
lines changed

3 files changed

+42
-15
lines changed

src/modbus.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -910,13 +910,14 @@ int modbus_reply(modbus_t *ctx,
910910
rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
911911
if (rsp_length != req_length) {
912912
/* Bad use of modbus_reply */
913-
rsp_length = response_exception(ctx,
914-
&sft,
915-
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
916-
rsp,
917-
FALSE,
918-
"Invalid request length (%d)\n",
919-
req_length);
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);
920921
break;
921922
}
922923

@@ -948,13 +949,26 @@ int modbus_reply(modbus_t *ctx,
948949
FALSE,
949950
"Illegal data address 0x%0X in write_register\n",
950951
address);
951-
} else {
952-
int data = (req[offset + 3] << 8) + req[offset + 4];
952+
break;
953+
}
953954

954-
mb_mapping->tab_registers[mapping_address] = data;
955-
memcpy(rsp, req, req_length);
956-
rsp_length = req_length;
955+
rsp_length = compute_response_length_from_request(ctx, (uint8_t *) req);
956+
if (rsp_length != req_length) {
957+
/* 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);
966+
break;
957967
}
968+
int data = (req[offset + 3] << 8) + req[offset + 4];
969+
970+
mb_mapping->tab_registers[mapping_address] = data;
971+
memcpy(rsp, req, rsp_length);
958972
} break;
959973
case MODBUS_FC_WRITE_MULTIPLE_COILS: {
960974
int nb = (req[offset + 3] << 8) + req[offset + 4];

tests/unit-test-client.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,13 +499,17 @@ int main(int argc, char *argv[])
499499

500500
modbus_disable_quirks(ctx, MODBUS_QUIRK_MAX_SLAVE);
501501
rc = modbus_set_slave(ctx, old_slave);
502-
ASSERT_TRUE(rc == 0, "Uanble to restore slave value")
502+
ASSERT_TRUE(rc == 0, "Unable to restore slave value")
503503

504504
/** BAD USE OF REPLY FUNCTION **/
505505
rc = modbus_write_bit(ctx, UT_BITS_ADDRESS_INVALID_REQUEST_LENGTH, ON);
506506
printf("* modbus_write_bit (triggers invalid reply): ");
507507
ASSERT_TRUE(rc == -1 && errno == EMBXILVAL, "");
508508

509+
rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS_SPECIAL, 0x42);
510+
printf("* modbus_write_register (triggers invalid reply): ");
511+
ASSERT_TRUE(rc == -1 && errno == EMBXILVAL, "");
512+
509513
/** SLAVE REPLY **/
510514

511515
printf("\nTEST SLAVE REPLY:\n");

tests/unit-test-server.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,17 @@ int main(int argc, char *argv[])
210210
// The valid length is lengths of header + checkum + FC + address + value
211211
// (max 12)
212212
rc = 34;
213-
printf("Special modbus_write_bit detected. Inject a wrong rc value (%d) "
214-
"in modbus_reply\n",
213+
printf(
214+
"Special modbus_write_bit detected. Inject a wrong length value (%d) "
215+
"in modbus_reply\n",
216+
rc);
217+
}
218+
} else if (query[header_length] == MODBUS_FC_WRITE_SINGLE_REGISTER) {
219+
if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1) ==
220+
UT_REGISTERS_ADDRESS_SPECIAL) {
221+
rc = 45;
222+
printf("Special modbus_write_register detected. Inject a wrong length "
223+
"value (%d) in modbus_reply\n",
215224
rc);
216225
}
217226
}

0 commit comments

Comments
 (0)