diff --git a/src/as-yamldata.c b/src/as-yamldata.c index edeb0204..00d197ad 100644 --- a/src/as-yamldata.c +++ b/src/as-yamldata.c @@ -137,7 +137,7 @@ as_yamldata_free_node (GNode *node, gpointer data) * Create GNode tree from DEP-11 YAML document */ static void -dep11_yaml_process_layer (yaml_parser_t *parser, GNode *data) +dep11_yaml_process_layer (yaml_parser_t *parser, GNode *data, GError **error) { GNode *last_leaf = data; GNode *last_scalar; @@ -147,7 +147,13 @@ dep11_yaml_process_layer (yaml_parser_t *parser, GNode *data) int storage = YAML_VAR; /* the first element must always be of type VAR */ while (parse) { - yaml_parser_parse (parser, &event); + if (!yaml_parser_parse (parser, &event)) { + g_set_error (error, + AS_METADATA_ERROR, + AS_METADATA_ERROR_FAILED, + "Invalid DEP-11 file found: YAML parsing error (%s)", parser->problem); + break; + } /* Parse value either as a new leaf in the mapping * or as a leaf value (one of them, in case it's a sequence) */ @@ -172,7 +178,9 @@ dep11_yaml_process_layer (yaml_parser_t *parser, GNode *data) last_scalar = last_leaf; if (in_sequence) last_leaf = g_node_append (last_leaf, g_node_new (g_strdup ("-"))); - dep11_yaml_process_layer (parser, last_leaf); + dep11_yaml_process_layer (parser, last_leaf, error); + if (*error != NULL) + parse = FALSE; last_leaf = last_scalar; storage ^= YAML_VAL; /* Flip VAR/VAL, without touching SEQ */ break; @@ -1839,7 +1847,14 @@ as_yamldata_parse_distro_data (AsYAMLData *ydt, const gchar *data, GError **erro yaml_parser_set_input_string (&parser, (unsigned char*) data, strlen (data)); while (parse) { - yaml_parser_parse (&parser, &event); + if (!yaml_parser_parse (&parser, &event)) { + g_set_error (error, + AS_METADATA_ERROR, + AS_METADATA_ERROR_FAILED, + "Invalid DEP-11 file found: YAML parsing error (%s)", parser.problem); + break; + } + if (event.type == YAML_DOCUMENT_START_EVENT) { GNode *n; gchar *key; @@ -1848,9 +1863,9 @@ as_yamldata_parse_distro_data (AsYAMLData *ydt, const gchar *data, GError **erro gboolean header_found = FALSE; GNode *root = g_node_new (g_strdup ("")); - dep11_yaml_process_layer (&parser, root); + dep11_yaml_process_layer (&parser, root, error); - if (header) { + if (header && *error == NULL) { for (n = root->children; n != NULL; n = n->next) { if ((n->data == NULL) || (n->children == NULL)) { parse = FALSE; @@ -1925,8 +1940,8 @@ as_yamldata_parse_distro_data (AsYAMLData *ydt, const gchar *data, GError **erro g_node_destroy (root); } - /* stop if end of stream is reached */ - if (event.type == YAML_STREAM_END_EVENT) + /* stop if end of stream is reached or error was encountered */ + if (event.type == YAML_STREAM_END_EVENT || *error != NULL) parse = FALSE; yaml_event_delete(&event); diff --git a/tests/test-yamldata.c b/tests/test-yamldata.c index 97fc203e..f185d224 100644 --- a/tests/test-yamldata.c +++ b/tests/test-yamldata.c @@ -177,20 +177,31 @@ test_yamlwrite (void) } AsComponent* -as_yaml_test_read_data (const gchar *data) +as_yaml_test_read_data (const gchar *data, GError **error) { - AsComponent *cpt; - GError *error = NULL; + AsComponent *cpt = NULL; g_autoptr(GPtrArray) cpts = NULL; g_autoptr(AsYAMLData) ydt = NULL; ydt = as_yamldata_new (); - cpts = as_yamldata_parse_distro_data (ydt, data, &error); - g_assert_no_error (error); + cpts = as_yamldata_parse_distro_data (ydt, data, error); - cpt = AS_COMPONENT (g_ptr_array_index (cpts, 0)); - return g_object_ref (cpt); + if (cpts->len > 0) { + cpt = AS_COMPONENT (g_ptr_array_index (cpts, 0)); + g_object_ref (cpt); + } + return cpt; +} + +AsComponent* +as_yaml_test_read_data_ok (const gchar *data) +{ + GError *error = NULL; + AsComponent *cpt = as_yaml_test_read_data (data, &error); + g_assert_no_error (error); + g_assert_nonnull (cpt); + return cpt; } void @@ -221,7 +232,7 @@ test_yaml_read_icons (void) ydt = as_yamldata_new (); /* check the legacy icons */ - cpt = as_yaml_test_read_data (yamldata_icons_legacy); + cpt = as_yaml_test_read_data_ok (yamldata_icons_legacy); g_assert_cmpstr (as_component_get_id (cpt), ==, "org.example.Test"); icons = as_component_get_icons (cpt); @@ -237,7 +248,7 @@ test_yaml_read_icons (void) /* check the new style icons tag */ g_object_unref (cpt); - cpt = as_yaml_test_read_data (yamldata_icons_current); + cpt = as_yaml_test_read_data_ok (yamldata_icons_current); g_assert_cmpstr (as_component_get_id (cpt), ==, "org.example.Test"); icons = as_component_get_icons (cpt); @@ -267,7 +278,7 @@ test_yaml_read_languages (void) " - locale: en_GB\n" " percentage: 100\n"; - cpt = as_yaml_test_read_data (yamldata_languages); + cpt = as_yaml_test_read_data_ok (yamldata_languages); g_assert_cmpstr (as_component_get_id (cpt), ==, "org.example.Test"); g_assert_cmpint (as_component_get_language (cpt, "de_DE"), ==, 48); @@ -275,6 +286,27 @@ test_yaml_read_languages (void) g_assert_cmpint (as_component_get_language (cpt, "invalid_C"), ==, -1); } +void +test_yaml_corrupt_data (void) +{ + GError *error = NULL; + g_autoptr(AsComponent) cpt = NULL; + const gchar *yamldata_corrupt = "---\n" + "ID: org.example.Test\n" + "\007\n"; + + cpt = as_yaml_test_read_data (yamldata_corrupt, &error); + + g_assert_error (error, AS_METADATA_ERROR, AS_METADATA_ERROR_FAILED); + g_assert_null (cpt); + + if (error != NULL) { + g_assert_true (g_str_has_prefix (error->message, "Invalid DEP-11 file found: YAML parsing error")); + g_error_free (error); + error = NULL; + } +} + int main (int argc, char **argv) { @@ -300,6 +332,7 @@ main (int argc, char **argv) g_test_add_func ("/YAML/Write", test_yamlwrite); g_test_add_func ("/YAML/Read/Icons", test_yaml_read_icons); g_test_add_func ("/YAML/Read/Languages", test_yaml_read_languages); + g_test_add_func ("/YAML/Read/Corrupt", test_yaml_corrupt_data); ret = g_test_run (); g_free (datadir);