Skip to content

Commit 8614a66

Browse files
committed
Properly copy XMD in set_xmd()
It's unsafe to call g_variant_new_from_data() with data living within another GVariant. The appropriate way to do this is to copy the data into a new buffer, then create the new GVariant from that (and set a GDestroyNotify function to free the buffer when it's done). Fixes: #274 Signed-off-by: Stephen Gallagher <[email protected]>
1 parent 305e0f3 commit 8614a66

File tree

5 files changed

+76
-11
lines changed

5 files changed

+76
-11
lines changed

modulemd/v2/modulemd-module-stream-v1.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ modulemd_module_stream_v1_set_xmd (ModulemdModuleStreamV1 *self, GVariant *xmd)
861861
g_return_if_fail (MODULEMD_IS_MODULE_STREAM_V1 (self));
862862

863863
g_clear_pointer (&self->xmd, g_variant_unref);
864-
self->xmd = xmd;
864+
self->xmd = modulemd_variant_deep_copy (xmd);
865865
}
866866

867867
GVariant *
@@ -1069,7 +1069,7 @@ modulemd_module_stream_v1_copy (ModulemdModuleStream *self,
10691069
copy, v1_self, servicelevels, modulemd_module_stream_v1_add_servicelevel);
10701070

10711071
if (v1_self->xmd != NULL)
1072-
modulemd_module_stream_v1_set_xmd (copy, g_variant_ref (v1_self->xmd));
1072+
modulemd_module_stream_v1_set_xmd (copy, v1_self->xmd);
10731073

10741074
return MODULEMD_MODULE_STREAM (g_steal_pointer (&copy));
10751075
}
@@ -1421,7 +1421,7 @@ modulemd_module_stream_v1_parse_yaml (ModulemdSubdocumentInfo *subdoc,
14211421
return NULL;
14221422
}
14231423
modulemd_module_stream_v1_set_xmd (modulestream, xmd);
1424-
xmd = NULL;
1424+
g_clear_pointer (&xmd, g_variant_unref);
14251425
}
14261426

14271427
/* Dependencies */

modulemd/v2/modulemd-util.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,15 +271,25 @@ modulemd_hash_table_unref (void *table)
271271
g_hash_table_unref ((GHashTable *)table);
272272
}
273273

274+
275+
static void
276+
destroy_variant_data (gpointer data)
277+
{
278+
g_free (data);
279+
}
280+
281+
274282
GVariant *
275283
modulemd_variant_deep_copy (GVariant *variant)
276284
{
277285
const GVariantType *data_type = g_variant_get_type (variant);
278286
gsize data_size = g_variant_get_size (variant);
279-
gconstpointer data = g_variant_get_data (variant);
287+
gpointer data = g_malloc0 (data_size);
288+
289+
g_variant_store (variant, data);
280290

281-
return g_variant_ref_sink (
282-
g_variant_new_from_data (data_type, data, data_size, TRUE, NULL, NULL));
291+
return g_variant_ref_sink (g_variant_new_from_data (
292+
data_type, data, data_size, FALSE, destroy_variant_data, data));
283293
}
284294

285295

modulemd/v2/modulemd-yaml-util.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,8 @@ modulemd_yaml_emit_variant (yaml_emitter_t *emitter,
957957
g_set_error (error,
958958
MODULEMD_YAML_ERROR,
959959
MODULEMD_YAML_ERROR_EMIT,
960-
"Unhandled variant type");
960+
"Unhandled variant type: \"%s\"",
961+
g_variant_get_type_string (variant));
961962
return FALSE;
962963
}
963964
return TRUE;

modulemd/v2/tests/ModulemdTests/modulestream.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,10 @@ def test_xmd(self):
528528

529529
xmd_copy = stream.get_xmd()
530530
assert xmd_copy
531-
assert 'outer_key' in xmd
532-
assert 'scalar' in xmd['outer_key']
533-
assert 'inner_key' in xmd['outer_key'][1]
534-
assert xmd['outer_key'][1]['inner_key'] == 'another_scalar'
531+
assert 'outer_key' in xmd_copy
532+
assert 'scalar' in xmd_copy['outer_key']
533+
assert 'inner_key' in xmd_copy['outer_key'][1]
534+
assert xmd_copy['outer_key'][1]['inner_key'] == 'another_scalar'
535535

536536
def test_upgrade(self):
537537
v1_stream = Modulemd.ModuleStreamV1.new("SuperModule", "latest")
@@ -1138,6 +1138,29 @@ def test_unicode_desc(self):
11381138
self.assertIsNotNone(stream)
11391139
self.assertTrue(stream.validate())
11401140

1141+
def test_xmd_issue_274(self):
1142+
# Test a valid module stream with unicode in the description
1143+
stream = Modulemd.ModuleStream.read_file(
1144+
"%s/modulemd/v2/tests/test_data/stream_unicode.yaml" %
1145+
(os.getenv('MESON_SOURCE_ROOT')), True, '', '')
1146+
1147+
# In this bug, we were getting a traceback attemping to call
1148+
# get_xmd() more than once on the same stream. There were subtle
1149+
# memory issues at play here.
1150+
if '_overrides_module' in dir(Modulemd):
1151+
# The XMD python tests can only be run against the installed lib
1152+
# because the overrides that translate between python and GVariant
1153+
# must be installed in /usr/lib/python*/site-packages/gi/overrides
1154+
# or they are not included when importing Modulemd
1155+
1156+
xmd = stream.get_xmd()
1157+
mbs_xmd = stream.get_xmd()['mbs']
1158+
mbs_xmd2 = stream.get_xmd()['mbs']
1159+
1160+
else:
1161+
stream.get_xmd()
1162+
stream.get_xmd()
1163+
11411164

11421165
if __name__ == '__main__':
11431166
unittest.main()

modulemd/v2/tests/test-modulemd-modulestream.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,35 @@ module_stream_v2_test_unicode_desc (void)
929929
}
930930

931931

932+
static void
933+
module_stream_v2_test_xmd_issue_274 (void)
934+
{
935+
g_autoptr (ModulemdModuleStream) stream = NULL;
936+
g_autofree gchar *path = NULL;
937+
g_autoptr (GError) error = NULL;
938+
GVariant *xmd1 = NULL;
939+
GVariant *xmd2 = NULL;
940+
941+
path = g_strdup_printf ("%s/modulemd/v2/tests/test_data/stream_unicode.yaml",
942+
g_getenv ("MESON_SOURCE_ROOT"));
943+
g_assert_nonnull (path);
944+
945+
stream = modulemd_module_stream_read_file (path, TRUE, NULL, NULL, &error);
946+
g_assert_nonnull (stream);
947+
g_assert_no_error (error);
948+
g_assert_cmpint (modulemd_module_stream_get_mdversion (stream),
949+
==,
950+
MD_MODULESTREAM_VERSION_ONE);
951+
952+
xmd1 =
953+
modulemd_module_stream_v1_get_xmd (MODULEMD_MODULE_STREAM_V1 (stream));
954+
xmd2 =
955+
modulemd_module_stream_v1_get_xmd (MODULEMD_MODULE_STREAM_V1 (stream));
956+
957+
g_assert_true (xmd1 == xmd2);
958+
}
959+
960+
932961
int
933962
main (int argc, char *argv[])
934963
{
@@ -1032,6 +1061,8 @@ main (int argc, char *argv[])
10321061
g_test_add_func ("/modulemd/v2/modulestream/v2/unicode/description",
10331062
module_stream_v2_test_unicode_desc);
10341063

1064+
g_test_add_func ("/modulemd/v2/modulestream/v2/xmd/issue274",
1065+
module_stream_v2_test_xmd_issue_274);
10351066

10361067
return g_test_run ();
10371068
}

0 commit comments

Comments
 (0)