resolve: fix use after free in DnsAnswer
This fixes a bug introduced by ae45e1a383
.
The set DnsAnswer::set_items contains the reference to the array in
DnsAnswer. So, the set must be reconstructed when we realloc() the
object.
Fixes #18132.
This commit is contained in:
parent
a084b38789
commit
0c2c0fd256
|
@ -664,6 +664,7 @@ int dns_answer_reserve(DnsAnswer **a, size_t n_free) {
|
||||||
|
|
||||||
if (*a) {
|
if (*a) {
|
||||||
size_t ns;
|
size_t ns;
|
||||||
|
int r;
|
||||||
|
|
||||||
if ((*a)->n_ref > 1)
|
if ((*a)->n_ref > 1)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -680,11 +681,23 @@ int dns_answer_reserve(DnsAnswer **a, size_t n_free) {
|
||||||
if (ns > UINT16_MAX)
|
if (ns > UINT16_MAX)
|
||||||
ns = UINT16_MAX;
|
ns = UINT16_MAX;
|
||||||
|
|
||||||
|
/* This must be done before realloc() below. Otherwise, the original DnsAnswer object
|
||||||
|
* may be broken. */
|
||||||
|
r = set_reserve((*a)->set_items, ns);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
n = realloc(*a, offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns);
|
n = realloc(*a, offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns);
|
||||||
if (!n)
|
if (!n)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
n->n_allocated = ns;
|
n->n_allocated = ns;
|
||||||
|
|
||||||
|
/* Previously all items are stored in the set, and the enough memory area is allocated
|
||||||
|
* in the above. So set_put() in the below cannot fail. */
|
||||||
|
set_clear(n->set_items);
|
||||||
|
for (size_t i = 0; i < n->n_rrs; i++)
|
||||||
|
assert_se(set_put(n->set_items, &n->items[i]) > 0);
|
||||||
} else {
|
} else {
|
||||||
n = dns_answer_new(n_free);
|
n = dns_answer_new(n_free);
|
||||||
if (!n)
|
if (!n)
|
||||||
|
|
Loading…
Reference in New Issue