Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/modbus-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ typedef int ssize_t;

#include "modbus.h"

/* select()/FD_SET treat a descriptor as an index into a fixed-size bitmask on
* POSIX, so a descriptor greater than or equal to FD_SETSIZE would write past
* the end of the fd_set and must be rejected. On Windows a SOCKET is an opaque
* handle whose numeric value is unrelated to FD_SETSIZE, and an fd_set is a
* counted array of sockets (fd_count + fd_array[]) rather than a bitmask. Since
* libmodbus only ever registers a single socket in a set, it can never overflow
* fd_array; the POSIX range check therefore does not apply on Windows and, if
* kept, wrongly rejects valid sockets whose handle value happens to reach
* FD_SETSIZE (64 by default). Restrict the check to non-Windows platforms. */
#if defined(_WIN32)
#define MODBUS_FD_OUT_OF_RANGE(fd) (0)
#else
#define MODBUS_FD_OUT_OF_RANGE(fd) ((fd) >= FD_SETSIZE)
#endif

MODBUS_BEGIN_DECLS

/* It's not really the minimal length (the real one is report slave ID
Expand Down
2 changes: 1 addition & 1 deletion src/modbus-rtu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ _modbus_rtu_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_t
}
/* Necessary after an error */
FD_ZERO(rset);
if (ctx->s < 0 || ctx->s >= FD_SETSIZE) {
if (ctx->s < 0 || MODBUS_FD_OUT_OF_RANGE(ctx->s)) {
errno = EINVAL;
return -1;
}
Expand Down
14 changes: 7 additions & 7 deletions src/modbus-tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ static int _connect(int sockfd,

/* Wait to be available in writing */
FD_ZERO(&wset);
if (sockfd >= FD_SETSIZE) {
if (MODBUS_FD_OUT_OF_RANGE(sockfd)) {
errno = EINVAL;
return -1;
}
Expand Down Expand Up @@ -363,7 +363,7 @@ static int _modbus_tcp_connect(modbus_t *ctx)
return -1;
}

if (s >= FD_SETSIZE) {
if (MODBUS_FD_OUT_OF_RANGE(s)) {
if (ctx->debug) {
fprintf(
stderr,
Expand Down Expand Up @@ -471,7 +471,7 @@ static int _modbus_tcp_pi_connect(modbus_t *ctx)
if (s < 0)
continue;

if (s >= FD_SETSIZE) {
if (MODBUS_FD_OUT_OF_RANGE(s)) {
if (ctx->debug) {
fprintf(
stderr,
Expand Down Expand Up @@ -550,7 +550,7 @@ static int _modbus_tcp_flush(modbus_t *ctx)
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rset);
if (ctx->s < 0 || ctx->s >= FD_SETSIZE) {
if (ctx->s < 0 || MODBUS_FD_OUT_OF_RANGE(ctx->s)) {
errno = EINVAL;
return -1;
}
Expand Down Expand Up @@ -805,7 +805,7 @@ int modbus_tcp_accept(modbus_t *ctx, int *s)
return -1;
}

if (ctx->s >= FD_SETSIZE) {
if (MODBUS_FD_OUT_OF_RANGE(ctx->s)) {
if (ctx->debug) {
fprintf(
stderr,
Expand Down Expand Up @@ -853,7 +853,7 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *s)
return -1;
}

if (ctx->s >= FD_SETSIZE) {
if (MODBUS_FD_OUT_OF_RANGE(ctx->s)) {
if (ctx->debug) {
fprintf(
stderr,
Expand Down Expand Up @@ -890,7 +890,7 @@ _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_t
}
/* Necessary after an error */
FD_ZERO(rset);
if (ctx->s < 0 || ctx->s >= FD_SETSIZE) {
if (ctx->s < 0 || MODBUS_FD_OUT_OF_RANGE(ctx->s)) {
errno = EINVAL;
return -1;
}
Expand Down
2 changes: 1 addition & 1 deletion src/modbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)

/* Add a file descriptor to the set */
FD_ZERO(&rset);
if (ctx->s < 0 || ctx->s >= FD_SETSIZE) {
if (ctx->s < 0 || MODBUS_FD_OUT_OF_RANGE(ctx->s)) {
if (ctx->debug) {
fprintf(stderr, "ERROR Invalid socket descriptor %d\n", ctx->s);
}
Expand Down