From 13c8ced533885c6e0f8a560b3c1a3b35240d1e52 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Tue, 12 May 2026 19:21:09 +0900 Subject: [PATCH 1/5] recv_packet: fix reported packet size on abnormal payloads --- src/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.c b/src/main.c index b86da5f..7ecd1b3 100644 --- a/src/main.c +++ b/src/main.c @@ -150,6 +150,7 @@ int recv_packet(int sockfd, rcon_packet_t *packet) { } packet->body[body_size] = '\0'; } else { + packet->size = sizeof(int32_t) * 2 + 2; packet->body[0] = '\0'; } -- 2.54.0 From 061101731c1d833ee77a268acdbbaaf74cc95c1c Mon Sep 17 00:00:00 2001 From: h7x4 Date: Tue, 12 May 2026 20:05:51 +0900 Subject: [PATCH 2/5] Makefile: build against C23 with GNU extensions --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d06b199..27a0fe8 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC = cc -CFLAGS = -std=c17 +CFLAGS = -std=gnu23 CFLAGS_WARNINGS = -Wall -Wextra CFLAGS_RELEASE = -O2 -fstack-protector-strong -fpie -s CFLAGS_DEBUG = -O0 -ggdb -DDEBUG -fsanitize=address -static-libasan -- 2.54.0 From ba31695c9b7b8d631b7b1af6e7a39a0631d14f58 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Tue, 12 May 2026 19:23:12 +0900 Subject: [PATCH 3/5] {send,recv}_packet: use compiler intrinsics to fix endianness on all platforms --- src/main.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/main.c b/src/main.c index 7ecd1b3..99dfa1c 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -82,20 +83,14 @@ void send_packet(int sockfd, int32_t id, int32_t type, const char *body) { return; } - packet[0] = size & 0xFF; - packet[1] = (size >> 8) & 0xFF; - packet[2] = (size >> 16) & 0xFF; - packet[3] = (size >> 24) & 0xFF; + int32_t size = htole32(packet_size - sizeof(int32_t)); + memcpy(packet, &size, sizeof(int32_t)); - packet[4] = id & 0xFF; - packet[5] = (id >> 8) & 0xFF; - packet[6] = (id >> 16) & 0xFF; - packet[7] = (id >> 24) & 0xFF; + int32_t id_ = htole32(id); + memcpy(packet + 4, &id_, sizeof(int32_t)); - packet[8] = type & 0xFF; - packet[9] = (type >> 8) & 0xFF; - packet[10] = (type >> 16) & 0xFF; - packet[11] = (type >> 24) & 0xFF; + int32_t type_ = htole32(type); + memcpy(packet + 8, &type_, sizeof(int32_t)); memcpy(packet + 12, body, body_len); packet[12 + body_len] = 0; @@ -123,6 +118,7 @@ int recv_packet(int sockfd, rcon_packet_t *packet) { } return -1; } + packet->size = le32toh(packet->size); if (packet->size < 10 || packet->size > 4110) { fprintf(stderr, "invalid packet size: %d\n", packet->size); @@ -134,12 +130,14 @@ int recv_packet(int sockfd, rcon_packet_t *packet) { perror("recv id failed"); return -1; } + packet->id = le32toh(packet->id); bytes = recv(sockfd, &packet->type, sizeof(int32_t), MSG_WAITALL); if (bytes <= 0) { perror("recv type failed"); return -1; } + packet->type = le32toh(packet->type); int body_size = packet->size - 10; if (body_size > 0 && body_size < (int)sizeof(packet->body)) { -- 2.54.0 From ef973d95320e39c66c90c352ebf2ae6909daf2aa Mon Sep 17 00:00:00 2001 From: h7x4 Date: Tue, 12 May 2026 19:25:23 +0900 Subject: [PATCH 4/5] {send,recv}_packet: embed last padding byte in package struct and fix sizes accordingly --- src/main.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main.c b/src/main.c index 99dfa1c..beccd82 100644 --- a/src/main.c +++ b/src/main.c @@ -18,10 +18,16 @@ const char *LOCALHOST = "127.0.0.1"; #define SERVERDATA_RESPONSE_VALUE 0 typedef struct { + // size of the remainder of the packet int32_t size; + // packet id (client sets, server echoes, -1 on auth failure) int32_t id; + // packet type (see the SERVERDATA_* constants) int32_t type; + // null-terminated command string (for auth and exec) or response string (from server) char body[4096]; + // yet another null byte after the body (required by protocol) + uint8_t _padding; } rcon_packet_t; int read_env_int(const char *var) { @@ -73,10 +79,9 @@ int rcon_connect(int port) { } void send_packet(int sockfd, int32_t id, int32_t type, const char *body) { - int body_len = strlen(body); - int32_t size = 10 + body_len; + size_t body_len = strlen(body); - size_t packet_size = sizeof(int32_t) + size; + size_t packet_size = sizeof(int32_t) * 3 + body_len + 2; unsigned char *packet = malloc(packet_size); if (!packet) { perror("malloc failed"); @@ -93,8 +98,8 @@ void send_packet(int sockfd, int32_t id, int32_t type, const char *body) { memcpy(packet + 8, &type_, sizeof(int32_t)); memcpy(packet + 12, body, body_len); - packet[12 + body_len] = 0; - packet[12 + body_len + 1] = 0; + packet[3 * sizeof(int32_t) + body_len] = 0; + packet[3 * sizeof(int32_t) + body_len + 1] = 0; ssize_t sent = send(sockfd, packet, packet_size, 0); if (sent < 0) { @@ -139,14 +144,20 @@ int recv_packet(int sockfd, rcon_packet_t *packet) { } packet->type = le32toh(packet->type); - int body_size = packet->size - 10; + int body_size = packet->size - sizeof(int32_t) * 2 - 2; if (body_size > 0 && body_size < (int)sizeof(packet->body)) { - bytes = recv(sockfd, packet->body, body_size + 2, MSG_WAITALL); + bytes = recv(sockfd, packet->body, body_size, MSG_WAITALL); if (bytes <= 0) { perror("recv body failed"); return -1; } packet->body[body_size] = '\0'; + + bytes = recv(sockfd, &packet->_padding, 1, MSG_WAITALL); + if (bytes <= 0) { + perror("recv padding failed"); + return -1; + } } else { packet->size = sizeof(int32_t) * 2 + 2; packet->body[0] = '\0'; -- 2.54.0 From 16b83475c220831a4b7adce00422604ef7bcd6e7 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Tue, 12 May 2026 19:26:00 +0900 Subject: [PATCH 5/5] recv_packet: calculate valid package sizes from struct size --- src/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index beccd82..d132223 100644 --- a/src/main.c +++ b/src/main.c @@ -30,6 +30,10 @@ typedef struct { uint8_t _padding; } rcon_packet_t; +// Minimum and maximum values for the `size` field of a valid packet. +#define MIN_SIZE (sizeof(int32_t) * 2 + 2) +#define MAX_SIZE (sizeof(rcon_packet_t) - sizeof(int32_t)) + int read_env_int(const char *var) { const char* port_str = getenv(var); if (port_str == NULL) { @@ -125,7 +129,7 @@ int recv_packet(int sockfd, rcon_packet_t *packet) { } packet->size = le32toh(packet->size); - if (packet->size < 10 || packet->size > 4110) { + if (packet->size < (int32_t)MIN_SIZE || packet->size > (int32_t)MAX_SIZE) { fprintf(stderr, "invalid packet size: %d\n", packet->size); return -1; } -- 2.54.0