Files
utun2/lib/memory_pool.c
T
evgeny 5c2501b4f3 chat: BGP-driven address sync, member identity verify, join_sig fix
- Адреса узлов вынесены из wire-протокола member_sync/merkle/join/welcome
  в BGP/topo_group: node_addresses теперь пишет только topo_node_sqlite_addrs_put
  (источник истины ni->v4/v6_addrs), классификация config_type/nat_type в sockmeta
- Жёсткая анти-подделка: node_id=derive(x25519), ed25519 сверяется с доверенной
  таблицей nodes, NODEINFO node_id/pubkey mismatch отклоняется как forgery
- Единые member_sync_build_join_msg (112Б) и member_sync_build_update_msg:
  устранён баг _verify_join_sig (join_ts по смещению 80 вместо 104, длина 104→112),
  который рушил приём мемберов; все 7 мест подписи/проверки join_sig через хелпер
- Единое обновление своего мембера chat_core_update_my_member (вместо sync_my_addresses)
- Android standby: пауза таймеров (broadcast/db_sync/merkle_sync/chat_sync) через standby_wait
- name[16] → name[MAX_CONN_NAME_LEN] с truncation-warning в парсере
- conn_mgr: etcp_connect_cancel_by_node (use-after-free при отмене invite),
  промоушен conn в ncd после успешного invite
- Android GUI: foreground-gating опросов, сохранение портов интерфейсов, фикс udp-log flush
- chatgui: персистентный db_path; мелкие DEBUG-логи epoll/pool
2026-08-15 12:36:05 +03:00

161 lines
5.2 KiB
C

// memory_pool.c
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "memory_pool.h"
#include "mem.h"
// Layout: [user_data: object_size] [canary: 4 bytes] [alloc_loc: pointer] [counter: 1 byte]
#define POOL_CANARY_OFF (pool->object_size)
#define POOL_LOC_OFF (pool->object_size + 4)
#define POOL_COUNTER_OFF (pool->object_size + 4 + sizeof(const char*))
#define POOL_ALLOC_SIZE (pool->object_size + 4 + sizeof(const char*) + 1)
#define POOL_CANARY_VAL 0xDEADBEAF
static void pool_init_tags(struct memory_pool* pool, void* obj, const char* location)
{
uint32_t* canary = (uint32_t*)((uint8_t*)obj + POOL_CANARY_OFF);
const char** loc = (const char**)((uint8_t*)obj + POOL_LOC_OFF);
uint8_t* counter = (uint8_t*)obj + POOL_COUNTER_OFF;
*canary = POOL_CANARY_VAL;
*loc = location;
*counter = 1;
}
static void pool_check_and_clear_tags(struct memory_pool* pool, void* obj, const char* location)
{
uint32_t* canary = (uint32_t*)((uint8_t*)obj + POOL_CANARY_OFF);
const char** loc = (const char**)((uint8_t*)obj + POOL_LOC_OFF);
uint8_t* counter = (uint8_t*)obj + POOL_COUNTER_OFF;
if (*canary != POOL_CANARY_VAL) {
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "pool_free BUFFER OVERFLOW pool=%p name=%s sz=%zu allocs=%zu reuse=%zu free=%d",
pool, pool->name ? pool->name : "?", pool->object_size, pool->allocations, pool->reuse_count, pool->free_count);
DEBUG_ERROR(DEBUG_CATEGORY_SYS, " obj=%p alloc=%s free=%s canary=0x%08x expected=0x%08x",
obj, *loc ? *loc : "(null)", location, *canary, POOL_CANARY_VAL);
if (pool->object_size)
log_dump(DEBUG_LEVEL_ERROR, DEBUG_CATEGORY_SYS, " user_data", obj, pool->object_size);
volatile int _halt = 1;
while (_halt) {}
}
if (*counter == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_SYS, "pool_free DOUBLE FREE pool=%p name=%s sz=%zu allocs=%zu reuse=%zu alloc=%s free=%s",
pool, pool->name ? pool->name : "?", pool->object_size, pool->allocations, pool->reuse_count,
*loc ? *loc : "(null)", location);
volatile int _halt = 1;
while (_halt) {}
}
*counter = 0;
}
static size_t g_total_free = 0;
size_t memory_pool_get_total_free_blocks(void) {
return g_total_free;
}
// Инициализировать пул памяти
struct memory_pool* memory_pool_init(size_t object_size, const char* name) {
struct memory_pool* pool = u_calloc(1, sizeof(struct memory_pool));
if (!pool) {
return NULL;
}
pool->free_head = NULL;
pool->object_size = object_size;
pool->free_count = 0;
pool->allocations = 0;
pool->reuse_count = 0;
pool->alloc_tag_counter = 1;
pool->name = name;
return pool;
}
// Выделить объект из пула или из malloc
void* memory_pool_alloc_impl(struct memory_pool* pool, const char* location) {
if (!pool) {
return NULL;
}
if (pool->free_head) {
void* obj = pool->free_head;
pool->free_head = *(void**)obj;
pool->free_count--;
g_total_free--;
pool->reuse_count++;
memset(obj, 0, pool->object_size);
pool_init_tags(pool, obj, location);
// DEBUG_TRACE(DEBUG_CATEGORY_SYS, "pool_alloc reused: %s, remaining=%zu", location, pool->free_count);
return obj;
}
pool->allocations++;
// DEBUG_TRACE(DEBUG_CATEGORY_SYS, "pool_alloc: %s, total_allocs=%zu", location, pool->allocations);
void* obj = u_calloc_impl(1, POOL_ALLOC_SIZE, location);
if (obj) pool_init_tags(pool, obj, location);
return obj;
}
// Освободить объект в пул или в free
void memory_pool_free_impl(struct memory_pool* pool, void* obj, const char* location) {
if (!pool || !obj) {
return;
}
pool_check_and_clear_tags(pool, obj, location);
if (pool->free_count < MEMORY_POOL_MAX_FREE) {
*(void**)obj = pool->free_head;
pool->free_head = obj;
pool->free_count++;
g_total_free++;
// DEBUG_TRACE(DEBUG_CATEGORY_SYS, "pool_free returned: %s, free_count=%zu", location, pool->free_count);
return;
}
// DEBUG_TRACE(DEBUG_CATEGORY_SYS, "pool_free direct: %s", location);
u_free_impl(obj, location);
}
// Получить статистику пула
void memory_pool_get_stats(struct memory_pool* pool, size_t* allocations, size_t* reuse_count) {
if (!pool) {
return;
}
if (allocations) {
*allocations = pool->allocations;
}
if (reuse_count) {
*reuse_count = pool->reuse_count;
}
}
// Очистить пул памяти
void memory_pool_destroy(struct memory_pool* pool) {
if (!pool) {
return;
}
void* obj = pool->free_head;
while (obj) {
void* next = *(void**)obj;
g_total_free--;
u_free(obj);
obj = next;
}
pool->free_head = NULL;
pool->free_count = 0;
u_free(pool);
}
int memory_pool_is_freed(struct memory_pool* pool, void* obj)
{
if (!pool || !obj) return 0;
void* cur = pool->free_head;
while (cur) {
if (cur == obj) return 1;
cur = *(void**)cur;
}
return 0;
}