blob: d11311731d4c06de0734fc72e82c55147283700e [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From db3235953baa56d2fb0e276ca510fefca751643f Mon Sep 17 00:00:00 2001
2From: Nanang Izzuddin <nanang@teluu.com>
3Date: Mon, 21 Feb 2022 06:24:52 +0700
4Subject: [PATCH] Merge pull request from GHSA-ffff-m5fm-qm62
5
6* Update pjsip_ua_unregister_dlg():
7- update the hash key if the dialog being unregistered is used as hash key.
8- add an assertion check to make sure that the dlg_set to be removed is valid (can be found in the hash table).
9
10* Change hash key string comparison method.
11---
12 pjsip/src/pjsip/sip_ua_layer.c | 48 +++++++++++++++++++++++++++++-----
13 1 file changed, 42 insertions(+), 6 deletions(-)
14
15--- a/pjsip/src/pjsip/sip_ua_layer.c
16+++ b/pjsip/src/pjsip/sip_ua_layer.c
17@@ -65,6 +65,9 @@ struct dlg_set
18 /* This is the buffer to store this entry in the hash table. */
19 pj_hash_entry_buf ht_entry;
20
21+ /* Entry key in the hash table */
22+ pj_str_t ht_key;
23+
24 /* List of dialog in this dialog set. */
25 struct dlg_set_head dlg_list;
26 };
27@@ -321,6 +324,7 @@ PJ_DEF(pj_status_t) pjsip_ua_register_dl
28 * Create the dialog set and add this dialog to it.
29 */
30 dlg_set = alloc_dlgset_node();
31+ dlg_set->ht_key = dlg->local.info->tag;
32 pj_list_init(&dlg_set->dlg_list);
33 pj_list_push_back(&dlg_set->dlg_list, dlg);
34
35@@ -328,8 +332,8 @@ PJ_DEF(pj_status_t) pjsip_ua_register_dl
36
37 /* Register the dialog set in the hash table. */
38 pj_hash_set_np_lower(mod_ua.dlg_table,
39- dlg->local.info->tag.ptr,
40- (unsigned)dlg->local.info->tag.slen,
41+ dlg_set->ht_key.ptr,
42+ (unsigned)dlg_set->ht_key.slen,
43 dlg->local.tag_hval, dlg_set->ht_entry,
44 dlg_set);
45 }
46@@ -339,14 +343,15 @@ PJ_DEF(pj_status_t) pjsip_ua_register_dl
47 struct dlg_set *dlg_set;
48
49 dlg_set = alloc_dlgset_node();
50+ dlg_set->ht_key = dlg->local.info->tag;
51 pj_list_init(&dlg_set->dlg_list);
52 pj_list_push_back(&dlg_set->dlg_list, dlg);
53
54 dlg->dlg_set = dlg_set;
55
56 pj_hash_set_np_lower(mod_ua.dlg_table,
57- dlg->local.info->tag.ptr,
58- (unsigned)dlg->local.info->tag.slen,
59+ dlg_set->ht_key.ptr,
60+ (unsigned)dlg_set->ht_key.slen,
61 dlg->local.tag_hval, dlg_set->ht_entry, dlg_set);
62 }
63
64@@ -391,12 +396,43 @@ PJ_DEF(pj_status_t) pjsip_ua_unregister_
65
66 /* If dialog list is empty, remove the dialog set from the hash table. */
67 if (pj_list_empty(&dlg_set->dlg_list)) {
68- pj_hash_set_lower(NULL, mod_ua.dlg_table, dlg->local.info->tag.ptr,
69- (unsigned)dlg->local.info->tag.slen,
70+
71+ /* Verify that the dialog set is valid */
72+ pj_assert(pj_hash_get_lower(mod_ua.dlg_table, dlg_set->ht_key.ptr,
73+ (unsigned)dlg_set->ht_key.slen,
74+ &dlg->local.tag_hval) == dlg_set);
75+
76+ pj_hash_set_lower(NULL, mod_ua.dlg_table, dlg_set->ht_key.ptr,
77+ (unsigned)dlg_set->ht_key.slen,
78 dlg->local.tag_hval, NULL);
79
80 /* Return dlg_set to free nodes. */
81 pj_list_push_back(&mod_ua.free_dlgset_nodes, dlg_set);
82+ } else {
83+ /* If the just unregistered dialog is being used as hash key,
84+ * reset the dlg_set entry with a new key (i.e: from the first dialog
85+ * in dlg_set).
86+ */
87+ if (dlg_set->ht_key.ptr == dlg->local.info->tag.ptr &&
88+ dlg_set->ht_key.slen == dlg->local.info->tag.slen)
89+ {
90+ pjsip_dialog* key_dlg = dlg_set->dlg_list.next;
91+
92+ /* Verify that the old & new keys share the hash value */
93+ pj_assert(key_dlg->local.tag_hval == dlg->local.tag_hval);
94+
95+ pj_hash_set_lower(NULL, mod_ua.dlg_table, dlg_set->ht_key.ptr,
96+ (unsigned)dlg_set->ht_key.slen,
97+ dlg->local.tag_hval, NULL);
98+
99+ dlg_set->ht_key = key_dlg->local.info->tag;
100+
101+ pj_hash_set_np_lower(mod_ua.dlg_table,
102+ dlg_set->ht_key.ptr,
103+ (unsigned)dlg_set->ht_key.slen,
104+ key_dlg->local.tag_hval, dlg_set->ht_entry,
105+ dlg_set);
106+ }
107 }
108
109 /* Unlock user agent. */