Verify deferred teardown when the TX timer cannot start

This commit is contained in:
evgeny committed 2026-10-22 22:47:50 +02:00
1 parent 0ef0553598
commit f37ac2c637
2 files changed
+22 -4

No files matched your search

+2 -1
View File
@@ -1012,7 +1012,8 @@ test_etcp_session_LDFLAGS = $(test_clock_ldflags)
test_etcp_windows_SOURCES = test_etcp_windows.c $(test_clock_sources)
test_etcp_windows_LDADD = $(LIBUTUN) $(COMMON_LIBS)
test_etcp_windows_LDFLAGS = $(test_clock_ldflags) -Wl,--wrap=etcp_encrypt_send -Wl,--wrap=memory_pool_alloc_impl -Wl,--wrap=bbr_main
test_etcp_windows_LDFLAGS = $(test_clock_ldflags) -Wl,--wrap=etcp_encrypt_send -Wl,--wrap=memory_pool_alloc_impl \\
-Wl,--wrap=bbr_main -Wl,--wrap=uasync_set_timeout
test_etcp_router_tcp_SOURCES = test_etcp_router_tcp.c
test_etcp_router_tcp_LDADD = $(LIBUTUN) $(COMMON_LIBS)
+20 -3
View File
@@ -16,7 +16,13 @@ static struct UTUN_INSTANCE inst;
static struct utun_config cfg;
static struct ETCP_CONN* conn;
static struct ETCP_LINK *a, *b;
static unsigned sends, fail_alloc, fail_send, bbr_calls, saw_cwnd_limited, saw_app_limited;
static unsigned sends, fail_alloc, fail_send, fail_tx_timer, bbr_calls, saw_cwnd_limited, saw_app_limited;
void* __real_uasync_set_timeout(struct UASYNC*, int, void*, timeout_callback_t, const char*);
void* __wrap_uasync_set_timeout(struct UASYNC* loop, int delay, void* arg, timeout_callback_t callback, const char* name) {
if (fail_tx_timer && !strcmp(name, "etcp_tx")) { fail_tx_timer--; return NULL; }
return __real_uasync_set_timeout(loop, delay, arg, callback, name);
}
int __wrap_etcp_encrypt_send(struct ETCP_DGRAM* pkt) {
CHECK(conn->tx_running && pkt->link && pkt->link->initialized && pkt->link->link_status);
@@ -56,7 +62,7 @@ static void check_accounting(void) {
static void setup(void) {
memset(&inst, 0, sizeof(inst)); memset(&cfg, 0, sizeof(cfg));
sends = fail_alloc = fail_send = bbr_calls = saw_cwnd_limited = saw_app_limited = 0;
sends = fail_alloc = fail_send = fail_tx_timer = bbr_calls = saw_cwnd_limited = saw_app_limited = 0;
ua = uasync_create(); CHECK(ua);
inst.ua = ua; inst.node_id = 1; inst.config = &cfg; cfg.global.bbr_max_cwnd = INFLIGHT_LIM_MAX;
inst.connections = queue_new(ua, 16, 0, 8, "windows");
@@ -277,13 +283,24 @@ static void config_limits(void) {
}
}
/* Отказ TX-таймера закрывает транспорт после выхода из вызывающего стека, без UAF очереди/линков. */
static void timer_failure(void) {
setup(); CHECK(!conn->tx_timer && etcp_conn_ref_take(conn) == 0);
fail_tx_timer = 1; enqueue(100);
CHECK(conn->close_requested && conn->close_token && conn->state != 2 && conn->links);
uasync_drain_immediate(ua);
CHECK(conn->state == 2 && !conn->tx_timer && !conn->links);
etcp_conn_ref_free(conn); teardown();
}
int main(void) {
debug_config_init(); debug_set_level(DEBUG_LEVEL_ERROR);
if (getenv("UTUN_TEST_DEBUG")) debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_DEBUG);
test_clock_init(10);
size_t baseline = u_get_allocated_count();
void (*cases[])(void) = {selection, boundaries_ack_burst, late_ack_and_migration, lost_ack_and_shrink,
grow_and_session, allocation_and_send_failure, removed_link_and_bbr, pacing_reset_close, initial_readiness, config_limits};
grow_and_session, allocation_and_send_failure, removed_link_and_bbr, pacing_reset_close, initial_readiness,
config_limits, timer_failure};
for (unsigned i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
cases[i](); CHECK(u_get_allocated_count() == baseline);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "PASS ETCP window scenario %u", i);