From a191eabef39b556c9aefc376516c3f524d7dc233 Mon Sep 17 00:00:00 2001 From: Akul123 Date: Mon, 3 Aug 2026 12:57:48 +0200 Subject: [PATCH] modbus_reply_exception: validate function code - modbus_reply_exception: reject function codes above 0x7F - Return EMBXILFUN when the request function already has the exception bit set instead of generating a wrapped response function code. - Added small test for the lower(0x80) and upper(0xFF) invalid boundaries. --- src/modbus.c | 6 +++++- tests/unit-test-client.c | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/modbus.c b/src/modbus.c index abdd718c..fe991864 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -1283,7 +1283,11 @@ int modbus_reply_exception(modbus_t *ctx, const uint8_t *req, unsigned int excep function = req[offset]; sft.slave = slave; - sft.function = function + 0x80; + if (function > 0x7F) { + errno = EMBXILFUN; /* Modbus: illegal function code */ + return -1; + } + sft.function = function | 0x80; sft.t_id = ctx->backend->get_response_tid(req); rsp_length = ctx->backend->build_response_basis(&sft, rsp); diff --git a/tests/unit-test-client.c b/tests/unit-test-client.c index c1542e97..bf9b01e7 100644 --- a/tests/unit-test-client.c +++ b/tests/unit-test-client.c @@ -779,6 +779,29 @@ int main(int argc, char *argv[]) printf("* modbus_read_registers at special address: "); ASSERT_TRUE(rc == -1 && errno == EMBXSBUSY, ""); + { + int i; + int header_length = modbus_get_header_length(ctx); + const uint8_t invalid_functions[] = {0x80, 0xFF}; + uint8_t invalid_req[MODBUS_TCP_MAX_ADU_LENGTH] = {0}; + + invalid_req[header_length - 1] = (use_backend == RTU) ? SERVER_ID : MODBUS_TCP_SLAVE; + + for (i = 0; i < 2; i++) { + invalid_req[header_length] = invalid_functions[i]; + + errno = 0; + rc = modbus_reply_exception( + ctx, invalid_req, MODBUS_EXCEPTION_ILLEGAL_FUNCTION); + + printf("* reject function code 0x%02X: ", invalid_functions[i]); + ASSERT_TRUE(rc == -1 && errno == EMBXILFUN, + "FAILED (rc=%d, errno=%d)\n", + rc, + errno); + } + } + /** Run a few tests to challenge the server code **/ if (test_server(ctx, use_backend) == -1) { goto close;