diff --git a/src/chat/chat_join.c b/src/chat/chat_join.c index 926643b5..e67091e8 100644 --- a/src/chat/chat_join.c +++ b/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; diff --git a/src/chat/chat_join.h b/src/chat/chat_join.h index 0c7ae1d8..c9423ba8 100644 --- a/src/chat/chat_join.h +++ b/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 если не влез. */ diff --git a/tests/test_chat_join.c b/tests/test_chat_join.c index 2717f368..5f9d4f70 100644 --- a/tests/test_chat_join.c +++ b/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(); } }