Merge pull request #739 from pprindeville/issue#738
[feed/telephony.git] / libs / pjproject / patches / 0171-dialog-set-free.patch
1 From db3235953baa56d2fb0e276ca510fefca751643f Mon Sep 17 00:00:00 2001
2 From: Nanang Izzuddin <nanang@teluu.com>
3 Date: Mon, 21 Feb 2022 06:24:52 +0700
4 Subject: [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. */