mirror of
https://github.com/transmission/transmission
synced 2025-01-30 19:03:04 +00:00
CVE-2018-10756: Fix heap-use-after-free in tr_variantWalk
In libtransmission/variant.c, function tr_variantWalk, when the variant stack is reallocated, a pointer to the previously allocated memory region is kept. This address is later accessed (heap use-after-free) while walking back down the stack, causing the application to crash. The application can be any application which uses libtransmission, such as transmission-daemon, transmission-gtk, transmission-show, etc. Reported-by: Tom Richards <tom@tomrichards.net>
This commit is contained in:
parent
a6482b0061
commit
2123adf8e5
1 changed files with 14 additions and 8 deletions
|
@ -758,7 +758,7 @@ static int compareKeyIndex(void const* va, void const* vb)
|
||||||
struct SaveNode
|
struct SaveNode
|
||||||
{
|
{
|
||||||
tr_variant const* v;
|
tr_variant const* v;
|
||||||
tr_variant sorted;
|
tr_variant* sorted;
|
||||||
size_t childIndex;
|
size_t childIndex;
|
||||||
bool isVisited;
|
bool isVisited;
|
||||||
};
|
};
|
||||||
|
@ -783,30 +783,36 @@ static void nodeConstruct(struct SaveNode* node, tr_variant const* v, bool sort_
|
||||||
|
|
||||||
qsort(tmp, n, sizeof(struct KeyIndex), compareKeyIndex);
|
qsort(tmp, n, sizeof(struct KeyIndex), compareKeyIndex);
|
||||||
|
|
||||||
tr_variantInitDict(&node->sorted, n);
|
node->sorted = tr_new(tr_variant, 1);
|
||||||
|
tr_variantInitDict(node->sorted, n);
|
||||||
|
|
||||||
for (size_t i = 0; i < n; ++i)
|
for (size_t i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
node->sorted.val.l.vals[i] = *tmp[i].val;
|
node->sorted->val.l.vals[i] = *tmp[i].val;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->sorted.val.l.count = n;
|
node->sorted->val.l.count = n;
|
||||||
|
|
||||||
tr_free(tmp);
|
tr_free(tmp);
|
||||||
|
|
||||||
node->v = &node->sorted;
|
v = node->sorted;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node->v = v;
|
node->sorted = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node->v = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nodeDestruct(struct SaveNode* node)
|
static void nodeDestruct(struct SaveNode* node)
|
||||||
{
|
{
|
||||||
if (node->v == &node->sorted)
|
TR_ASSERT(node != NULL);
|
||||||
|
|
||||||
|
if (node->sorted != NULL)
|
||||||
{
|
{
|
||||||
tr_free(node->sorted.val.l.vals);
|
tr_free(node->sorted->val.l.vals);
|
||||||
|
tr_free(node->sorted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue