diff options
author | Aleš Matěj <amatej@redhat.com> | 2022-02-22 16:32:22 +0300 |
---|---|---|
committer | Neal Gompa (ニール・ゴンパ) <ngompa13@gmail.com> | 2022-03-07 17:55:06 +0300 |
commit | 2cf2d9f83b269bd570bca69c03c94251b080e5dd (patch) | |
tree | 49c126c33c3b1ae8103e7a1cb99eb0e541ab33b8 | |
parent | 0932975c5079e8ef650d2f10847ee474d906879f (diff) |
Fix a memory leak of primary pkg when parsing interrupted
This is not a problem for `filelists` or `other` because when they create
their package they immediately add it to in_progress_pkgs_list.
Add unit tests for interrupting parsing in filelists and other.
-rw-r--r-- | src/xml_parser_main_metadata_together.c | 18 | ||||
-rw-r--r-- | tests/python/tests/test_xml_parser.py | 19 |
2 files changed, 32 insertions, 5 deletions
diff --git a/src/xml_parser_main_metadata_together.c b/src/xml_parser_main_metadata_together.c index af2aa58..ef8212d 100644 --- a/src/xml_parser_main_metadata_together.c +++ b/src/xml_parser_main_metadata_together.c @@ -432,9 +432,17 @@ out: } } - cr_xml_parser_data_free(primary_pd); - cr_xml_parser_data_free(filelists_pd); - cr_xml_parser_data_free(other_pd); + // When interrupted at the right time primary_pd->pkg can either be: + // - referenced in both primary_pd->pkg and cbdata.in_progress_pkgs_list or + // - referenced only in primary_pd->pkg (we have started parsing the pkg but didn't finish it yet) + // in order to avoid a crash remove it from the list if present + // primary_pd->pkg is a special case because of newpkgcb_primary + if (cbdata.in_progress_pkgs_list) { + cbdata.in_progress_pkgs_list = g_slist_remove(cbdata.in_progress_pkgs_list, primary_pd->pkg); + } + if (primary_pd) { + cr_package_free(primary_pd->pkg); + } if (cbdata.newpkgcb) { g_slist_free(cbdata.in_progress_pkgs_list); @@ -442,5 +450,9 @@ out: cr_slist_free_full(cbdata.in_progress_pkgs_list, (GDestroyNotify) cr_package_free); } + cr_xml_parser_data_free(primary_pd); + cr_xml_parser_data_free(filelists_pd); + cr_xml_parser_data_free(other_pd); + return ret; } diff --git a/tests/python/tests/test_xml_parser.py b/tests/python/tests/test_xml_parser.py index c835710..1adadc7 100644 --- a/tests/python/tests/test_xml_parser.py +++ b/tests/python/tests/test_xml_parser.py @@ -1119,13 +1119,28 @@ class TestCaseXmlParserMainMetadataTogether(unittest.TestCase): return pkg self.assertRaises(cr.CreaterepoCError, cr.xml_parse_main_metadata_together, - PRIMARY_ERROR_00_PATH, FILELISTS_ERROR_00_PATH, - OTHER_ERROR_00_PATH, newpkgcb, None, None) + PRIMARY_ERROR_00_PATH, REPO_02_FILXML, + REPO_02_OTHXML, newpkgcb, None, None) # unlike parsing just primary, filelists or other separately when parsing together primary is parsed first fully # before newpkgcb is called so the error is detected before any user package is created self.assertEqual(len(userdata["pkgs"]), 0) + # test when the error is filelists + self.assertRaises(cr.CreaterepoCError, cr.xml_parse_main_metadata_together, + REPO_02_PRIXML, FILELISTS_ERROR_00_PATH, + REPO_02_OTHXML, newpkgcb, None, None) + + self.assertEqual(len(userdata["pkgs"]), 2) + + # test when the error is other + userdata = { "pkgs": [] } + self.assertRaises(cr.CreaterepoCError, cr.xml_parse_main_metadata_together, + REPO_02_PRIXML, REPO_02_FILXML, + OTHER_ERROR_00_PATH, newpkgcb, None, None) + + self.assertEqual(len(userdata["pkgs"]), 2) + def test_xml_parser_main_metadata_together_newpkgcb_abort(self): def newpkgcb(pkgId, name, arch): raise Error("Foo error") |