Files
utun2/lib/strbuf.c
T
evgeny f2228202e3 fix: FORTIFY vsnprintf crash on Android + foreground service type
Root cause: etcp_on_up/etcp_on_down/etcp_conn_process_send_queue
used fixed buffers (links_str[256], l_status[256]) with snprintf
chains in loops over links. With 15+ links (IPv6 addresses),
sizeof(buf)-offset turned negative → vsnprintf size=(size_t)(-17)
→ FORTIFY abort on Bionic.

Fixes:
- lib/strbuf.h/c: safe growable printf buffer (auto-realloc)
- etcp.c: 3 snprintf chains → strbuf
- debug_config.c: BUF_ADVANCE macro prevents offset overflow
- android_jni_bridge.c: bridge_log va_list fix, set_member_flags guard
- chat_core.c: TAGS_ADVANCE macro in tags_commit
- AndroidManifest.xml: dataSync→specialUse (time limit exhausted)
- stcp: ed25519 pubkey exchange, tcp link addr/status in JNI bridge
- etcp_router: encrypted flag + ECDH per peer-pair
- node_conn_direct: TCP link support
- topo_node: group nodes cleanup
- media_delivery: buffer overflow fix
- test_stcp: ed25519 key exchange test
- tests: invite_group_create + Makefile update
2026-08-10 00:11:30 +03:00

80 lines
2.0 KiB
C

/*
* strbuf.c — safe growable printf buffer
*/
#include "strbuf.h"
#include "mem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRBUF_MIN_CAP 16
void strbuf_init(struct strbuf *sb, size_t initial_cap) {
if (initial_cap < STRBUF_MIN_CAP) initial_cap = STRBUF_MIN_CAP;
sb->buf = u_malloc(initial_cap);
if (sb->buf) { sb->buf[0] = '\0'; sb->cap = initial_cap; }
else { sb->cap = 0; }
sb->len = 0;
}
void strbuf_free(struct strbuf *sb) {
if (sb->buf) { u_free(sb->buf); sb->buf = NULL; }
sb->cap = 0; sb->len = 0;
}
char *strbuf_detach(struct strbuf *sb) {
char *ret = sb->buf;
sb->buf = NULL; sb->cap = 0; sb->len = 0;
return ret;
}
void strbuf_reset(struct strbuf *sb) {
if (sb->buf) sb->buf[0] = '\0';
sb->len = 0;
}
static int strbuf_grow(struct strbuf *sb, size_t need) {
size_t nc = sb->cap ? sb->cap : STRBUF_MIN_CAP;
while (nc < need) { nc *= 2; if (nc < STRBUF_MIN_CAP) return -1; }
char *n = u_realloc(sb->buf, nc);
if (!n) return -1;
sb->buf = n; sb->cap = nc;
return 0;
}
int strbuf_addf(struct strbuf *sb, const char *fmt, ...) {
va_list ap;
/* measure */
va_start(ap, fmt);
int need = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
if (need < 0) { return -1; }
/* grow */
size_t want = sb->len + (size_t)need + 1; /* +1 for '\0' */
if (want > sb->cap && strbuf_grow(sb, want) < 0) return -1;
/* write */
va_start(ap, fmt);
int w = vsnprintf(sb->buf + sb->len, sb->cap - sb->len, fmt, ap);
va_end(ap);
if (w > 0) sb->len += (size_t)w;
return w;
}
void strbuf_addc(struct strbuf *sb, char c) {
if (sb->len + 2 > sb->cap && strbuf_grow(sb, sb->len + 2) < 0) return;
sb->buf[sb->len++] = c;
sb->buf[sb->len] = '\0';
}
void strbuf_adds(struct strbuf *sb, const char *s) {
if (!s) return;
size_t slen = strlen(s);
if (sb->len + slen + 1 > sb->cap && strbuf_grow(sb, sb->len + slen + 1) < 0) return;
memcpy(sb->buf + sb->len, s, slen);
sb->len += slen;
sb->buf[sb->len] = '\0';
}