This is an automated email from the ASF dual-hosted git repository. pengzheng pushed a commit to branch feature/527-manifest-improvement in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/feature/527-manifest-improvement by this push: new 660994dd Fix broken manifest_clone. 660994dd is described below commit 660994ddb7bfc0df9db617adadd0de03f54dc56c Author: PengZheng <howto...@gmail.com> AuthorDate: Fri Aug 11 21:33:45 2023 +0800 Fix broken manifest_clone. Fix double free of keys when destroying the clone. Clone mainAttributes when cloning. --- libs/framework/gtest/src/ManifestTestSuite.cc | 80 ++++++++++++++++++---- libs/framework/include_deprecated/manifest.h | 4 ++ libs/framework/src/manifest.c | 31 +++++---- .../gtest/src/CelixUtilsAutoCleanupTestSuite.cc | 2 +- 4 files changed, 89 insertions(+), 28 deletions(-) diff --git a/libs/framework/gtest/src/ManifestTestSuite.cc b/libs/framework/gtest/src/ManifestTestSuite.cc index ce58d294..401dfd04 100644 --- a/libs/framework/gtest/src/ManifestTestSuite.cc +++ b/libs/framework/gtest/src/ManifestTestSuite.cc @@ -26,22 +26,44 @@ class ManifestTestSuite : public ::testing::Test { protected: - manifest_pt manifest = nullptr; - void SetUp() override { - ASSERT_EQ(CELIX_SUCCESS, manifest_create(&manifest)); - } - void TearDown() override { - manifest_destroy(manifest); - } + manifest_pt manifest = nullptr; + void SetUp() override { + ASSERT_EQ(CELIX_SUCCESS, manifest_create(&manifest)); + } + void TearDown() override { + manifest_destroy(manifest); + } + void CheckPropertiesEqual(const celix_properties_t* prop1, const celix_properties_t* prop2) { + EXPECT_EQ(celix_properties_size(prop1), celix_properties_size(prop2)); + const char* key = nullptr; + CELIX_PROPERTIES_FOR_EACH(prop1, key) { + EXPECT_STREQ(celix_properties_get(prop1, key, nullptr), celix_properties_get(prop2, key, nullptr)); + } + } + void CheckManifestEqual(const manifest_pt manifest1, const manifest_pt manifest2) { + CheckPropertiesEqual(manifest_getMainAttributes(manifest1), manifest_getMainAttributes(manifest2)); + hash_map_pt entries1 = nullptr; + EXPECT_EQ(CELIX_SUCCESS, manifest_getEntries(manifest1, &entries1)); + hash_map_pt entries2 = nullptr; + EXPECT_EQ(CELIX_SUCCESS, manifest_getEntries(manifest2, &entries2)); + EXPECT_EQ(hashMap_size(entries1), hashMap_size(entries2)); + hash_map_iterator_t iter = hashMapIterator_construct(entries1); + while (hashMapIterator_hasNext(&iter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); + celix_properties_t* value1 = (celix_properties_t*)hashMapEntry_getValue(entry); + celix_properties_t* value2 = (celix_properties_t*)hashMap_get(entries2, hashMapEntry_getKey(entry)); + CheckPropertiesEqual(value1, value2); + } + } }; TEST_F(ManifestTestSuite, EmptyManifestTest) { - const celix_properties_t* mainAttr = manifest_getMainAttributes(manifest); - EXPECT_EQ(0, celix_properties_size(mainAttr)); - hash_map_pt entries = nullptr; - EXPECT_EQ(CELIX_SUCCESS, manifest_getEntries(manifest, &entries)); - EXPECT_NE(nullptr, entries); - EXPECT_EQ(0, hashMap_size(entries)); + const celix_properties_t* mainAttr = manifest_getMainAttributes(manifest); + EXPECT_EQ(0, celix_properties_size(mainAttr)); + hash_map_pt entries = nullptr; + EXPECT_EQ(CELIX_SUCCESS, manifest_getEntries(manifest, &entries)); + EXPECT_NE(nullptr, entries); + EXPECT_EQ(0, hashMap_size(entries)); } TEST_F(ManifestTestSuite, ReadManifestWithoutNameSectionsTest) { @@ -107,4 +129,36 @@ TEST_F(ManifestTestSuite, ReadManifestWithNameSectionsTest) { EXPECT_STREQ("N8Ow2UY4yjnHZv5zeq2I1Uv/+uE=", celix_properties_get(entry2, "SHA1-Digest", nullptr)); EXPECT_STREQ("com.third._3d.native", celix_properties_get(entry2, "Bundle-SymbolicName", nullptr)); EXPECT_STREQ("1.5.3", celix_properties_get(entry2, "Bundle-Version", nullptr)); +} + +TEST_F(ManifestTestSuite, CleanupTest) { + celix_auto(manifest_pt) manifest2 = nullptr; + EXPECT_EQ(CELIX_SUCCESS, manifest_create(&manifest2)); + celix_auto(manifest_pt) manifest3 = nullptr; + EXPECT_EQ(CELIX_SUCCESS, manifest_create(&manifest3)); + EXPECT_EQ(CELIX_SUCCESS, manifest_destroy(celix_steal_ptr(manifest3))); +} + +TEST_F(ManifestTestSuite, CloneTest) { + std::string content = "Manifest-Version: 1.0\n" + "DeploymentPackage-Icon: %icon\n" + "DeploymentPackage-SymbolicName: com.third._3d\n" + "DeploymentPacakge-Version: 1.2.3.build22032005\n" + "\n" + "Name: bundles/3dlib.jar\n" + "SHA1-Digest: MOez1l4gXHBo8ycYdAxstK3UvEg=\n" + "Bundle-SymbolicName: com.third._3d\n" + "Bundle-Version: 2.3.1\n" + "\n" + "Name: bundles/3dnative.jar\n" + "SHA1-Digest: N8Ow2UY4yjnHZv5zeq2I1Uv/+uE=\n" + "Bundle-SymbolicName: com.third._3d.native\n" + "Bundle-Version: 1.5.3\n" + "\n"; + celix_autoptr(FILE) manifestFile = tmpfile(); + EXPECT_EQ(content.size(), fwrite(content.c_str(), 1, content.size(), manifestFile)); + rewind(manifestFile); + EXPECT_EQ(CELIX_SUCCESS, manifest_readFromStream(manifest, manifestFile)); + celix_auto(manifest_pt) clone = manifest_clone(manifest); + CheckManifestEqual(manifest, clone); } \ No newline at end of file diff --git a/libs/framework/include_deprecated/manifest.h b/libs/framework/include_deprecated/manifest.h index 89e6f578..e4c4d629 100644 --- a/libs/framework/include_deprecated/manifest.h +++ b/libs/framework/include_deprecated/manifest.h @@ -27,9 +27,11 @@ #ifndef MANIFEST_H_ #define MANIFEST_H_ +#include <stddef.h> #include <stdio.h> #include "properties.h" +#include "celix_cleanup.h" #include "celix_errno.h" #include "celix_framework_export.h" @@ -52,6 +54,8 @@ CELIX_FRAMEWORK_DEPRECATED_EXPORT celix_status_t manifest_createFromFile(const c CELIX_FRAMEWORK_DEPRECATED_EXPORT celix_status_t manifest_destroy(manifest_pt manifest); +CELIX_DEFINE_AUTO_CLEANUP_FREE_FUNC(manifest_pt, manifest_destroy, NULL) + CELIX_FRAMEWORK_DEPRECATED_EXPORT void manifest_clear(manifest_pt manifest); CELIX_FRAMEWORK_DEPRECATED_EXPORT celix_properties_t *manifest_getMainAttributes(manifest_pt manifest); diff --git a/libs/framework/src/manifest.c b/libs/framework/src/manifest.c index 11e83860..ca838f65 100644 --- a/libs/framework/src/manifest.c +++ b/libs/framework/src/manifest.c @@ -54,22 +54,25 @@ celix_status_t manifest_create(manifest_pt *manifest) { } manifest_pt manifest_clone(manifest_pt manifest) { - celix_status_t status = CELIX_SUCCESS; + celix_status_t status = CELIX_SUCCESS; - manifest_pt clone = NULL; - status = manifest_create(&clone); - if (status == CELIX_SUCCESS) { - hash_map_iterator_t iter = hashMapIterator_construct(manifest->attributes); - while (hashMapIterator_hasNext(&iter)) { - hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); - char *key = hashMapEntry_getKey(entry); - celix_properties_t* value = hashMapEntry_getValue(entry); - celix_properties_t* cloneValue = celix_properties_copy(value); - hashMap_put(clone->attributes, key, cloneValue); - } - } + manifest_pt clone = NULL; + status = manifest_create(&clone); + if (status == CELIX_SUCCESS) { + const char* key = NULL; + CELIX_PROPERTIES_FOR_EACH(manifest->mainAttributes, key) { + celix_properties_set(clone->mainAttributes, key, celix_properties_get(manifest->mainAttributes, key, NULL)); + } + hash_map_iterator_t iter = hashMapIterator_construct(manifest->attributes); + while (hashMapIterator_hasNext(&iter)) { + hash_map_entry_pt entry = hashMapIterator_nextEntry(&iter); + celix_properties_t* value = hashMapEntry_getValue(entry); + celix_properties_t* cloneValue = celix_properties_copy(value); + hashMap_put(clone->attributes, strdup(hashMapEntry_getKey(entry)), cloneValue); + } + } - return clone; + return clone; } celix_status_t manifest_destroy(manifest_pt manifest) { diff --git a/libs/utils/gtest/src/CelixUtilsAutoCleanupTestSuite.cc b/libs/utils/gtest/src/CelixUtilsAutoCleanupTestSuite.cc index eeb3fae3..a74a6f33 100644 --- a/libs/utils/gtest/src/CelixUtilsAutoCleanupTestSuite.cc +++ b/libs/utils/gtest/src/CelixUtilsAutoCleanupTestSuite.cc @@ -192,4 +192,4 @@ TEST_F(CelixUtilsCleanupTestSuite, StealFdTest) { TEST_F(CelixUtilsCleanupTestSuite, FileTest) { celix_autoptr(FILE) file = tmpfile(); -} \ No newline at end of file +}