mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
gvariant-serialiser: Factor out functions for dealing with framing offsets
This introduces no functional changes. Helps: #2121
This commit is contained in:
parent
1deacdd4e8
commit
446e69f5ed
@ -635,30 +635,62 @@ gvs_calculate_total_size (gsize body_size,
|
||||
return body_size + 8 * offsets;
|
||||
}
|
||||
|
||||
static gsize
|
||||
gvs_variable_sized_array_n_children (GVariantSerialised value)
|
||||
struct Offsets
|
||||
{
|
||||
gsize data_size;
|
||||
|
||||
guchar *array;
|
||||
gsize length;
|
||||
guint offset_size;
|
||||
|
||||
gboolean is_normal;
|
||||
};
|
||||
|
||||
static gsize
|
||||
gvs_offsets_get_offset_n (struct Offsets *offsets,
|
||||
gsize n)
|
||||
{
|
||||
return gvs_read_unaligned_le (
|
||||
offsets->array + (offsets->offset_size * n), offsets->offset_size);
|
||||
}
|
||||
|
||||
static struct Offsets
|
||||
gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
|
||||
{
|
||||
struct Offsets out = { 0, };
|
||||
gsize offsets_array_size;
|
||||
gsize offset_size;
|
||||
gsize last_end;
|
||||
|
||||
if (value.size == 0)
|
||||
return 0;
|
||||
{
|
||||
out.is_normal = TRUE;
|
||||
return out;
|
||||
}
|
||||
|
||||
offset_size = gvs_get_offset_size (value.size);
|
||||
|
||||
last_end = gvs_read_unaligned_le (value.data + value.size -
|
||||
offset_size, offset_size);
|
||||
out.offset_size = gvs_get_offset_size (value.size);
|
||||
last_end = gvs_read_unaligned_le (value.data + value.size - out.offset_size,
|
||||
out.offset_size);
|
||||
|
||||
if (last_end > value.size)
|
||||
return 0;
|
||||
return out; /* offsets not normal */
|
||||
|
||||
offsets_array_size = value.size - last_end;
|
||||
|
||||
if (offsets_array_size % offset_size)
|
||||
return 0;
|
||||
if (offsets_array_size % out.offset_size)
|
||||
return out; /* offsets not normal */
|
||||
|
||||
return offsets_array_size / offset_size;
|
||||
out.data_size = last_end;
|
||||
out.array = value.data + last_end;
|
||||
out.length = offsets_array_size / out.offset_size;
|
||||
out.is_normal = TRUE;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static gsize
|
||||
gvs_variable_sized_array_n_children (GVariantSerialised value)
|
||||
{
|
||||
return gvs_variable_sized_array_get_frame_offsets (value).length;
|
||||
}
|
||||
|
||||
static GVariantSerialised
|
||||
@ -666,8 +698,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
gsize index_)
|
||||
{
|
||||
GVariantSerialised child = { 0, };
|
||||
gsize offset_size;
|
||||
gsize last_end;
|
||||
|
||||
struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
|
||||
|
||||
gsize start;
|
||||
gsize end;
|
||||
|
||||
@ -675,18 +708,11 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
g_variant_type_info_ref (child.type_info);
|
||||
child.depth = value.depth + 1;
|
||||
|
||||
offset_size = gvs_get_offset_size (value.size);
|
||||
|
||||
last_end = gvs_read_unaligned_le (value.data + value.size -
|
||||
offset_size, offset_size);
|
||||
|
||||
if (index_ > 0)
|
||||
{
|
||||
guint alignment;
|
||||
|
||||
start = gvs_read_unaligned_le (value.data + last_end +
|
||||
(offset_size * (index_ - 1)),
|
||||
offset_size);
|
||||
start = gvs_offsets_get_offset_n (&offsets, index_ - 1);
|
||||
|
||||
g_variant_type_info_query (child.type_info, &alignment, NULL);
|
||||
start += (-start) & alignment;
|
||||
@ -694,11 +720,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
else
|
||||
start = 0;
|
||||
|
||||
end = gvs_read_unaligned_le (value.data + last_end +
|
||||
(offset_size * index_),
|
||||
offset_size);
|
||||
end = gvs_offsets_get_offset_n (&offsets, index_);
|
||||
|
||||
if (start < end && end <= value.size && end <= last_end)
|
||||
if (start < end && end <= value.size && end <= offsets.data_size)
|
||||
{
|
||||
child.data = value.data + start;
|
||||
child.size = end - start;
|
||||
@ -770,34 +794,16 @@ static gboolean
|
||||
gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
{
|
||||
GVariantSerialised child = { 0, };
|
||||
gsize offsets_array_size;
|
||||
guchar *offsets_array;
|
||||
guint offset_size;
|
||||
guint alignment;
|
||||
gsize last_end;
|
||||
gsize length;
|
||||
gsize offset;
|
||||
gsize i;
|
||||
|
||||
if (value.size == 0)
|
||||
return TRUE;
|
||||
struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
|
||||
|
||||
offset_size = gvs_get_offset_size (value.size);
|
||||
last_end = gvs_read_unaligned_le (value.data + value.size -
|
||||
offset_size, offset_size);
|
||||
|
||||
if (last_end > value.size)
|
||||
if (!offsets.is_normal)
|
||||
return FALSE;
|
||||
|
||||
offsets_array_size = value.size - last_end;
|
||||
|
||||
if (offsets_array_size % offset_size)
|
||||
return FALSE;
|
||||
|
||||
offsets_array = value.data + value.size - offsets_array_size;
|
||||
length = offsets_array_size / offset_size;
|
||||
|
||||
if (length == 0)
|
||||
if (value.size != 0 && offsets.length == 0)
|
||||
return FALSE;
|
||||
|
||||
child.type_info = g_variant_type_info_element (value.type_info);
|
||||
@ -805,14 +811,14 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
child.depth = value.depth + 1;
|
||||
offset = 0;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
for (i = 0; i < offsets.length; i++)
|
||||
{
|
||||
gsize this_end;
|
||||
|
||||
this_end = gvs_read_unaligned_le (offsets_array + offset_size * i,
|
||||
offset_size);
|
||||
this_end = gvs_read_unaligned_le (offsets.array + offsets.offset_size * i,
|
||||
offsets.offset_size);
|
||||
|
||||
if (this_end < offset || this_end > last_end)
|
||||
if (this_end < offset || this_end > offsets.data_size)
|
||||
return FALSE;
|
||||
|
||||
while (offset & alignment)
|
||||
@ -834,7 +840,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
offset = this_end;
|
||||
}
|
||||
|
||||
g_assert (offset == last_end);
|
||||
g_assert (offset == offsets.data_size);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user