mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-22 08:57:17 -06:00
Bug 799324 - Invalid free in gvalue_from_kvp_value()
As of ddc3f28899
, gvalue_from_kvp_value()
takes a GValue pointer from the caller, which in some cases points to
memory on the stack. If that is the case and the code also hits the
default case in the switch statement, the unconditional g_slice_free()
call will attempt to free stack memory, causing the program to abort.
Fix by requiring the caller to always pass in a valid GValue pointer,
making the caller responsible for freeing it if necessary. This also
means that it is no longer necessary for gvalue_from_kvp_value() to
return a value, so make it a void function.
This commit is contained in:
parent
5c716cc95c
commit
c4d44ea024
@ -232,14 +232,11 @@ int compare(const KvpFrameImpl & one, const KvpFrameImpl & two) noexcept
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GValue*
|
void
|
||||||
gvalue_from_kvp_value (const KvpValue *kval, GValue* val)
|
gvalue_from_kvp_value (const KvpValue *kval, GValue* val)
|
||||||
{
|
{
|
||||||
if (kval == NULL) return NULL;
|
if (kval == NULL) return;
|
||||||
if (!val)
|
g_value_unset(val);
|
||||||
val = g_slice_new0 (GValue);
|
|
||||||
else
|
|
||||||
g_value_unset(val);
|
|
||||||
|
|
||||||
switch (kval->get_type())
|
switch (kval->get_type())
|
||||||
{
|
{
|
||||||
@ -274,11 +271,8 @@ gvalue_from_kvp_value (const KvpValue *kval, GValue* val)
|
|||||||
default:
|
default:
|
||||||
/* No transfer outside of QofInstance-derived classes! */
|
/* No transfer outside of QofInstance-derived classes! */
|
||||||
PWARN ("Error! Invalid attempt to transfer Kvp type %d", kval->get_type());
|
PWARN ("Error! Invalid attempt to transfer Kvp type %d", kval->get_type());
|
||||||
g_slice_free (GValue, val);
|
|
||||||
val = NULL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KvpValue*
|
KvpValue*
|
||||||
|
@ -175,9 +175,9 @@ KvpValueImpl::set(T val) noexcept
|
|||||||
/** @internal @{ */
|
/** @internal @{ */
|
||||||
/** Convert a kvp_value into a GValue. Frames aren't converted.
|
/** Convert a kvp_value into a GValue. Frames aren't converted.
|
||||||
* @param kval: A KvpValue.
|
* @param kval: A KvpValue.
|
||||||
* @return GValue*. Must be freed with g_free().
|
* @param val: The GValue in which to store the converted value.
|
||||||
*/
|
*/
|
||||||
GValue* gvalue_from_kvp_value (const KvpValue *kval, GValue* val = nullptr);
|
void gvalue_from_kvp_value (const KvpValue *kval, GValue* val);
|
||||||
|
|
||||||
/** Convert a gvalue into a kvpvalue.
|
/** Convert a gvalue into a kvpvalue.
|
||||||
* @param gval: A GValue of a type KvpValue can digest.
|
* @param gval: A GValue of a type KvpValue can digest.
|
||||||
|
@ -1317,11 +1317,11 @@ static void
|
|||||||
wrap_gvalue_function (const char* key, KvpValue *val, wrap_param & param)
|
wrap_gvalue_function (const char* key, KvpValue *val, wrap_param & param)
|
||||||
{
|
{
|
||||||
GValue *gv;
|
GValue *gv;
|
||||||
|
gv = g_slice_new0 (GValue);
|
||||||
if (val->get_type() != KvpValue::Type::FRAME)
|
if (val->get_type() != KvpValue::Type::FRAME)
|
||||||
gv = gvalue_from_kvp_value(val);
|
gvalue_from_kvp_value(val, gv);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gv = g_slice_new0 (GValue);
|
|
||||||
g_value_init (gv, G_TYPE_STRING);
|
g_value_init (gv, G_TYPE_STRING);
|
||||||
g_value_set_string (gv, nullptr);
|
g_value_set_string (gv, nullptr);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user