7 Commits

Author SHA1 Message Date
5bb776c432 fix(server): check kill_recv in accept() loop to prevent hang on stop
If server_stop() is called before any client connects, the accept()
loop would spin forever since kill_recv was never checked, causing
pthread_join() to block indefinitely.

Add kill_recv check at the top of the accept() polling loop so the
thread can exit cleanly when server_stop() is called during the
pre-connection phase.
2026-03-12 11:51:56 +03:00
1c36292b1f fix(server): remove invalid recv() call on listen socket
The recv() drain loop on listen_socket was incorrect - listen sockets
don't have data to read. This caused Valgrind to report 'points to
unaddressable byte(s)' errors during functional tests.

Replaced magic number 2 with SHUT_RDWR for clarity.
2026-01-13 17:13:41 +03:00
79fe9dc2b3 fix: use valid buffer in recv() instead of NULL 2025-12-31 09:55:22 +03:00
0353d31355 Fix race condition in log_println (use-after-free)
The check for logready was done BEFORE acquiring the lock, causing a race
condition with log_close(). If log_close() runs between the check and
the lock acquisition, the log file would be closed but log_println would
still try to write to it (use-after-free).

Now the logready/logp check is inside the critical section.
2025-12-25 23:04:13 +03:00
afa4a3a4ea Fix GString memory leak in read_stream function
The 'stream' GString was not freed before returning from read_stream()
in two places:
1. When kill_recv is TRUE at the start of the loop
2. At the end of the function after the loop exits

Added g_string_free(stream, TRUE) before both return statements.
2025-12-25 22:47:10 +03:00
6579e9f565 Fix: Pass valid buffer to recv() instead of NULL
Valgrind reports:
  Syscall param socketcall.recvfrom(buf) points to unaddressable byte(s)
  at recv (recv.c:28)
  by xmppclient_end_session (xmppclient.c:57)
  Address 0x0 is not stack'd, malloc'd or (recently) free'd

The recv() call was passing NULL as buffer, which is invalid.
Now using a local char variable as discard buffer.
2025-12-25 20:42:32 +03:00
7a222fc446 fix: Free XMPPStanza objects in verify_any and verify_last
The XMPPStanza objects created by stanza_parse() in verify_any() and
verify_last() functions were never freed, causing memory leaks.

This fix adds stanza_free(stanza) calls before the return statements
to properly release the allocated stanza resources.
2025-12-24 16:52:40 +03:00
4 changed files with 16 additions and 6 deletions

View File

@@ -70,11 +70,14 @@ log_init(stbbr_log_t loglevel)
void
log_println(stbbr_log_t loglevel, const char * const msg, ...)
{
if (!logready || loglevel < minlevel) {
pthread_mutex_lock(&loglock);
// Check logready AFTER acquiring lock to prevent race with log_close
if (!logready || !logp || loglevel < minlevel) {
pthread_mutex_unlock(&loglock);
return;
}
pthread_mutex_lock(&loglock);
va_list arg;
va_start(arg, msg);
GString *fmt_msg = g_string_new(NULL);

View File

@@ -109,6 +109,7 @@ read_stream(void)
while (TRUE) {
if (kill_recv) {
_shutdown();
g_string_free(stream, TRUE);
return 0;
}
@@ -167,6 +168,7 @@ read_stream(void)
memset(buf, 0, sizeof(buf));
}
g_string_free(stream, TRUE);
return 0;
}
@@ -434,8 +436,12 @@ _start_server_cb(void* userdata)
int c = sizeof(struct sockaddr_in);
int client_socket;
errno = 0;
// DEBUG removed
while ((client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, (socklen_t*)&c)) == -1) {
if (kill_recv) {
log_println(STBBR_LOGINFO, "Accept loop interrupted by stop request");
_shutdown();
return NULL;
}
if (errno != EAGAIN && errno != EWOULDBLOCK) {
log_println(STBBR_LOGERROR, "Accept failed: %s", strerror(errno));
return NULL;
@@ -475,8 +481,7 @@ _shutdown(void)
parser_close();
shutdown(listen_socket, 2);
while (recv(listen_socket, NULL, 1, 0) > 0) {}
shutdown(listen_socket, SHUT_RDWR);
close(listen_socket);
prime_free_all();

View File

@@ -72,6 +72,7 @@ verify_any(char *stanza_text, gboolean ign_timeout)
log_println(STBBR_LOGINFO, "VERIFY FAIL: %s", stanza_text);
}
stanza_free(stanza);
return result;
}
@@ -106,5 +107,6 @@ verify_last(char *stanza_text)
stanzas_debug_last();
}
stanza_free(stanza);
return result;
}

View File

@@ -54,7 +54,7 @@ xmppclient_end_session(XMPPClient *client)
if (client->sock) {
shutdown(client->sock, 2);
while (recv(client->sock, NULL, 1, 0) > 0) {}
char discard_buf; while (recv(client->sock, &discard_buf, 1, 0) > 0) {}
close(client->sock);
}
free(client->ip);