Maybe a use-after-free in function lsquic_engine_destroy
In figure 1, in function lsquic_engine.c::lsquic_engine_destroy, force_close_conn->lsquic_attq_pop may result in a use-after-free.
When calling force_close_conn, we may call lsquic_add_conn_to_attq first(in file lsquic_send_ctl.c) and then call free(conn)(in file lsquic_full_conn_ietf.c), as shown in figure 2 3.
During the period after calling lsquic_add_conn_to_attq and before free(conn), if time_handler does not execute prog_process_conns (probably because the timer is not triggered), then there will be a use-after-free when executing lsquic_attq_pop in Figure 1 (because the conn is already freed).
Briefly, the correct process is lsquic_attq_add -> time_handler (lsquic_attq_pop is called) -> free(conn) -> lsquic_attq_pop (return null). And there is no use-after-free. But if time_handler is not executed during the period, the process will be lsquic_attq_add -> free(conn) (free)-> lsquic_attq_pop (use:return the wild pointer conn), and there will be a use-after-free.
So I guess it's better to actively execute prog_process_conns once instead of relying purely on the timer function prog_timer_handler before free(conn) is called.
I think it has been taken care of in https://github.com/litespeedtech/lsquic/blob/b46a5b19bb372d531b567bf899452149c533eb87/src/liblsquic/lsquic_engine.c#L1906-L1910
No further update, I assume it is a false positive.