type_check_is_value_type_U crashing with SEGV
In our system we are using glib-2.48.2, which is crashing with SEGV signal in a function type_check_is_value_type_U
(gtype.c file). I have checked master branch as well if this particular function function looks the same and it does, so issue might be still there, even on newest glib version.
This is our callstack:
thread-37 tid=20330 faulted
[0] /usr/lib/libgobject-2.0.so.0.4800.2!type_check_is_value_type_U [/usr/src/debug/glib-2.0/1_2.48.2-r0/glib-2.48.2/gobject/gtype.c : 4172 + 0x2]
[1] /usr/lib/libgobject-2.0.so.0.4800.2!g_type_check_value [/usr/src/debug/glib-2.0/1_2.48.2-r0/glib-2.48.2/gobject/gtype.c : 4206 + 0x5]
[2] /usr/lib/libgstreamer-1.0.so.0.1004.0!gst_value_init_and_copy [/usr/src/debug/gstreamer1.0/1.10.4-r0/gstreamer-1.10.4/gst/gstvalue.c : 5241 + 0x3]
[3] /usr/lib/libgstreamer-1.0.so.0.1004.0!gst_structure_copy [/usr/src/debug/gstreamer1.0/1.10.4-r0/gstreamer-1.10.4/gst/gststructure.c : 353 + 0x3]
[4] /usr/lib/libgstreamer-1.0.so.0.1004.0!_gst_caps_copy [/usr/src/debug/gstreamer1.0/1.10.4-r0/gstreamer-1.10.4/gst/gstcaps.c : 183 + 0x3]
This particular place is leading us to below code chunk:
...
4169 if (node)
4170 {
4171 if (node->data && NODE_REFCOUNT (node) > 0 &&
4172 node->data->common.value_table->value_init)
...
There are two issues here:
- how do we know if
data
member does haveCommonData
as its active member? We might end up here with UB as per spec: https://en.cppreference.com/w/cpp/language/union
It's undefined behavior to read from the member of the union that wasn't most recently written.
- Let's assume that
data
member does haveCommonData
as its active member. How do we know ifvalue_table
is a valid pointer?
I have prepared minimal example to reproduce that issue:
#include <iostream>
struct ValueTable
{
int value_init;
};
struct CommonData
{
ValueTable* value_table;
};
struct BoxedData
{
double boxedCode;
};
union TypeData
{
CommonData common;
BoxedData boxed;
};
struct TypeNode
{
TypeData* volatile data;
};
int main()
{
TypeNode* node = new TypeNode();
node->data = new TypeData();
node->data->boxed = BoxedData{5.6}; // TypeData::boxed gets initialized
std::cout << "Before if\n";
if (node && node->data && node->data->common.value_table->value_init) // checking wrong union member here; SEGV
// and value_table was not initialized as well here
{
std::cout << "Inside IF\n";
std::cout << "value_init: " << node->data->common.value_table->value_init << "\n";
}
else
{
std::cout << "ELSE\n";
}
std::cout << "after if\n";
delete node->data;
delete node;
return 0;
}
Console output:
Before if
Segmentation fault (core dumped)
Besides the two above issues I think we have another one. Let's look at below code chunk:
...
4181 TypeNode *prnode = lookup_type_node_I (prtype);
4182
4183 if (prnode->is_instantiatable)
...
I think we should do a sanity check here if prnode
was indeed initialized here (similar to line 4164).
Edited by g3t0r1x