Skip to content

Commit

Permalink
Update TCP proxy to address Coverity errors
Browse files Browse the repository at this point in the history
Coverity seems to have some problems with the loop(s) copying data from
one socket to another, in that it assume that eventually an integer
overflow will occur. It's not obvious why this should be flagged, but
this seems likely to be a false positive.

This commit avoids the integer issue by using a simple pointer + count
mechanism.

The socket copy code has been placed in a separate function - before it
was duplicated. Minor fixes have been made to error reporting around the
connection code.
  • Loading branch information
matt335672 committed Feb 4, 2025
1 parent d924440 commit 90df425
Showing 1 changed file with 76 additions and 83 deletions.
159 changes: 76 additions & 83 deletions tools/devel/tcp_proxy/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ int g_loc_io_count = 0; // bytes read from local port
int g_rem_io_count = 0; // bytes read from remote port

static int g_terminated = 0;
static char g_buf[1024 * 32];


typedef unsigned short tui16;

Expand All @@ -67,6 +65,69 @@ g_tcp_socket_ok(int sck)
return 0;
}

/*****************************************************************************/
static int
copy_sck_to_sck(int from_sck, int to_sck, int hexdump, int local)
{
char buff[1024 * 32];
int rv = -1;

int count = g_tcp_recv(from_sck, buff, sizeof(buff), 0);
if (count > 0 && count <= (int)sizeof(buff))
{
rv = count; // Assume we'll return the amount of data copied
if (local)
{
g_loc_io_count += count;
if (hexdump)
{
LOG_HEXDUMP(LOG_LEVEL_INFO, "from local:", buff, count);
}
}
else
{
g_rem_io_count += count;
if (hexdump)
{
LOG_HEXDUMP(LOG_LEVEL_INFO, "from remote:", buff, count);
}
}


LOG(LOG_LEVEL_DEBUG, "local_io_count: %d\tremote_io_count: %d",
g_loc_io_count, g_rem_io_count);

const char *p = buff;
while ((count > 0) && (!g_terminated))
{
int error = g_tcp_send(to_sck, p, count, 0);

if (error > 0)
{
// We wrote some data
count -= error;
p += error;
continue;
}

if ((error == -1) && g_tcp_last_error_would_block(to_sck))
{
if (g_tcp_can_send(to_sck, 1000))
{
g_tcp_socket_ok(to_sck);
}
}
else
{
count = 0; // Terminate loop
rv = -1; // tell user
}
}
}

return rv;
}

/*****************************************************************************/
static int
main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
Expand All @@ -76,7 +137,6 @@ main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
int con_sck = -1;
int sel;
int count;
int sent;
int error;
int i;
int acc_to_con = 0;
Expand Down Expand Up @@ -165,9 +225,8 @@ main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
error = 0;
i = 0;

while (!(g_tcp_can_send(con_sck, 100) && g_tcp_socket_ok(con_sck))
&& (!g_terminated)
&& (i < 100))
while (!g_terminated && i < 100 &&
!g_tcp_can_send(con_sck, 100))
{
g_sleep(100);
i++;
Expand All @@ -178,8 +237,7 @@ main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
LOG(LOG_LEVEL_ERROR, "timeout connecting");
error = 1;
}

if (g_terminated)
else if (!g_tcp_socket_ok(con_sck))
{
error = 1;
}
Expand All @@ -191,7 +249,7 @@ main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
}
}

while ((!g_terminated) && (error == 0))
while (!g_terminated)
{
sel = g_tcp_select(con_sck, acc_sck);

Expand All @@ -204,87 +262,22 @@ main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
if (sel & 1)
{
// can read from con_sck w/o blocking
count = g_tcp_recv(con_sck, g_buf, 1024 * 16, 0);
error = count < 1;

if (error == 0)
count = copy_sck_to_sck(con_sck, acc_sck, hexdump, 1);
if (count < 0)
{
g_loc_io_count += count;
con_to_acc += count;

if (hexdump)
{
LOG_HEXDUMP(LOG_LEVEL_INFO, "from remove, the socket from connect", g_buf, count);
}

LOG(LOG_LEVEL_DEBUG, "local_io_count: %d\tremote_io_count: %d",
g_loc_io_count, g_rem_io_count);
sent = 0;

while ((sent < count) && (error == 0) && (!g_terminated))
{
i = g_tcp_send(acc_sck, g_buf + sent, count - sent, 0);

if ((i == -1) && g_tcp_last_error_would_block(acc_sck))
{
if (g_tcp_can_send(acc_sck, 1000))
{
g_tcp_socket_ok(acc_sck);
}
}
else if (i < 1)
{
error = 1;
}
else
{
sent += i;
}
}
break;
}
con_to_acc += count;
}

if (sel & 2)
{
// can read from acc_sck w/o blocking
count = g_tcp_recv(acc_sck, g_buf, 1024 * 16, 0);
error = count < 1;

if (error == 0)
count = copy_sck_to_sck(acc_sck, con_sck, hexdump, 0);
if (count < 0)
{
g_rem_io_count += count;
acc_to_con += count;

if (hexdump)
{
LOG_HEXDUMP(LOG_LEVEL_INFO, "from accepted, the socket from accept", g_buf, count);
}

LOG(LOG_LEVEL_DEBUG, "local_io_count: %d\tremote_io_count: %d",
g_loc_io_count, g_rem_io_count);
sent = 0;

while ((sent < count) && (error == 0) && (!g_terminated))
{
i = g_tcp_send(con_sck, g_buf + sent, count - sent, 0);

if ((i == -1) && g_tcp_last_error_would_block(con_sck))
{
if (g_tcp_can_send(con_sck, 1000))
{
g_tcp_socket_ok(con_sck);
}
}
else if (i < 1 || i > (count - sent))
{
error = 1;
}
else
{
sent += i;
}
}
}
break;
};
acc_to_con += count;
}
}

Expand Down

0 comments on commit 90df425

Please sign in to comment.