From 01e2de64af2f6bb94c5d6c81b22b817fb6933bf1 Mon Sep 17 00:00:00 2001 From: Fabrice Bellet Date: Fri, 1 Oct 2021 12:17:19 +0200 Subject: agent: ensure suceeded and discovered pairs fail the same time This patch ensures that related succeeded-discovered pairs change to state failed simultaneously, to avoid leaving dangling pointers if one is freeed while the other is still in the conncheck list. Such transition is very rare, and only occurs in regular nomination mode, when the network conditions change between the time the pair is initially discovered and the time it is rechecked with the use-candidate flag. --- agent/conncheck.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/agent/conncheck.c b/agent/conncheck.c index e03130a..960698b 100644 --- a/agent/conncheck.c +++ b/agent/conncheck.c @@ -630,6 +630,20 @@ candidate_check_pair_fail (NiceStream *stream, NiceAgent *agent, CandidateCheckP component = nice_stream_find_component_by_id (stream, p->component_id); SET_PAIR_STATE (agent, p, NICE_CHECK_FAILED); priv_free_all_stun_transactions (p, component); + + /* Ensure related succeeded-discovered pairs change to state failed + * simultaneously, to avoid leaving dangling pointers if one is freeed + * while the other is still in the conncheck list. Such transition is + * very rare, and only occurs in regular nomination mode, when the + * network conditions change between the time the pair is initially + * discovered and the time it is rechecked with the use-candidate + * flag. + */ + if (p->discovered_pair != NULL) { + nice_debug ("Agent %p : related discovered pair %p of pair %p " + "will fail too.", agent, p->discovered_pair, p); + SET_PAIR_STATE (agent, p->discovered_pair, NICE_CHECK_FAILED); + } } /* @@ -3435,6 +3449,14 @@ static CandidateCheckPair *priv_process_response_check_for_reflexive(NiceAgent * */ if (new_pair == p) p->valid = TRUE; + else + /* this new_pair distinct from p may also be in state failed (if + * the related succeeded pair p was in state failed previously, but + * retriggered a successful check a bit later), so we force its + * state back to discovered there. + */ + SET_PAIR_STATE (agent, new_pair, NICE_CHECK_DISCOVERED); + SET_PAIR_STATE (agent, p, NICE_CHECK_SUCCEEDED); priv_remove_pair_from_triggered_check_queue (agent, p); priv_free_all_stun_transactions (p, component); -- cgit v1.2.1