Browse Source

Use bounded 16-bit profile lengths in join member records

master
evgeny 6 days ago
parent
commit
c04f51d424
  1. 18
      src/chat/chat_join.c
  2. 2
      src/chat/chat_join.h
  3. 10
      tests/test_chat_join.c

18
src/chat/chat_join.c

@ -104,8 +104,11 @@ static void _keys_free_all(struct UTUN_INSTANCE* inst) {
int chat_join_serialize_member(const struct join_member_data* m,
uint8_t* out, size_t out_sz, size_t* out_len) {
if (!m || !out || !out_len || !m->x25519 || !m->ed25519) return -1;
size_t ul = strnlen(m->userinfo, 255);
size_t need = 8 + 32 + 32 + 64 + 8 + 64 + 8 + 1 + ul;
size_t ul = strnlen(m->userinfo, sizeof(m->userinfo));
if (ul > MS_USERINFO_MAX) {
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "chat_join: profile exceeds limit bytes=%zu", ul); return -1;
}
size_t need = 8 + 32 + 32 + 64 + 8 + 64 + 8 + 2 + ul;
if (need > out_sz) return -1;
size_t off = 0;
memcpy(out + off, &m->node_id, 8); off += 8;
@ -115,7 +118,7 @@ int chat_join_serialize_member(const struct join_member_data* m,
memcpy(out + off, &m->join_ts, 8); off += 8;
if (m->update_sig) memcpy(out + off, m->update_sig, 64); else memset(out + off, 0, 64); off += 64;
memcpy(out + off, &m->update_ts, 8); off += 8;
out[off++] = (uint8_t)ul;
out[off++] = (uint8_t)(ul >> 8); out[off++] = (uint8_t)ul;
if (ul) memcpy(out + off, m->userinfo, ul);
off += ul;
*out_len = off;
@ -123,7 +126,7 @@ int chat_join_serialize_member(const struct join_member_data* m,
}
int chat_join_parse_member(const uint8_t* data, size_t len, struct join_member_data* m) {
if (!data || !m || len < 8 + 32 + 32 + 64 + 8 + 64 + 8 + 1) return -1;
if (!data || !m || len < 8 + 32 + 32 + 64 + 8 + 64 + 8 + 2) return -1;
memset(m, 0, sizeof(*m));
size_t off = 0;
memcpy(&m->node_id, data + off, 8); off += 8;
@ -133,9 +136,10 @@ int chat_join_parse_member(const uint8_t* data, size_t len, struct join_member_d
memcpy(&m->join_ts, data + off, 8); off += 8;
m->update_sig = data + off; off += 64;
memcpy(&m->update_ts, data + off, 8); off += 8;
uint8_t ul = data[off++];
if (off + ul > len) return -1;
if (ul > 255) ul = 255;
size_t ul = ((size_t)data[off] << 8) | data[off + 1]; off += 2;
if (ul > MS_USERINFO_MAX || off + ul != len || memchr(data + off, 0, ul)) {
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "chat_join: invalid profile length bytes=%zu payload=%zu", ul, len); return -1;
}
memcpy(m->userinfo, data + off, ul);
m->userinfo[ul] = '\0';
return 0;

2
src/chat/chat_join.h

@ -109,7 +109,7 @@ struct join_member_data {
uint64_t join_ts; /* время подписи вступления, Unix seconds */
const uint8_t* update_sig; /* 64, может быть NULL */
uint64_t update_ts; /* версия подписанного блока участника */
char userinfo[256]; /* JSON, null-terminated */
char userinfo[1025]; /* JSON до MS_USERINFO_MAX байт, null-terminated */
};
/* Сериализовать member-блок (без join_key). Возвращает 0 и *out_len, -1 если не влез. */

10
tests/test_chat_join.c

@ -254,15 +254,15 @@ static void t_serialize_parse(void) {
if (chat_join_parse_member(buf, 10, &p) == -1) OK(); else FAIL();
}
TEST("serialize_member: userinfo up to 255"); {
char ui[256]; memset(ui, 'a', 255); ui[255] = '\0';
TEST("serialize_member: userinfo up to 1024"); {
char ui[1025]; memset(ui, 'a', 1024); ui[1024] = '\0';
struct join_member_data ml = m; ml.userinfo[0] = '\0';
memcpy(ml.userinfo, ui, 256);
uint8_t b2[512]; size_t l2 = 0;
memcpy(ml.userinfo, ui, sizeof(ui));
uint8_t b2[1400]; size_t l2 = 0;
struct join_member_data p; memset(&p, 0, sizeof(p));
if (chat_join_serialize_member(&ml, b2, sizeof(b2), &l2) != 0
|| chat_join_parse_member(b2, l2, &p) != 0
|| strlen(p.userinfo) != 255 || memcmp(p.userinfo, ui, 255) != 0) FAIL();
|| strlen(p.userinfo) != 1024 || memcmp(p.userinfo, ui, 1024) != 0) FAIL();
else OK();
}
}

Loading…
Cancel
Save