From 79ff9b4fb6e21be10f65d3e8138c3cf36e18bda0 Mon Sep 17 00:00:00 2001 From: Seungha Son Date: Fri, 4 Aug 2017 10:16:49 +0900 Subject: [PATCH] Add OOM exception handler Signed-off-by: Seungha Son Change-Id: Ib23567136a901d8a9a833b23db3292abeaef2177 --- src/common/external_storage.cc | 26 +++++++-- src/common/plugins/types/category_plugin.cc | 11 ++++ src/common/plugins/types/metadata_plugin.cc | 23 +++++++- src/common/privileges.cc | 19 +++++++ .../step/configuration/step_parse_manifest.cc | 66 +++++++++++++++++++++- .../step/security/step_privilege_compatibility.cc | 12 ++++ 6 files changed, 148 insertions(+), 9 deletions(-) diff --git a/src/common/external_storage.cc b/src/common/external_storage.cc index 4c67eab..9117e17 100644 --- a/src/common/external_storage.cc +++ b/src/common/external_storage.cc @@ -28,6 +28,14 @@ int64_t SizeInMB(int64_t size) { return (size + 1_MB - 1) / 1_MB; } +void ClearApp2ExtDirDetail(gpointer data) { + app2ext_dir_details* dir_detail = + reinterpret_cast(data); + if (dir_detail->name) + free(dir_detail->name); + free(dir_detail); +} + } // namespace namespace common_installer { @@ -158,7 +166,18 @@ bool ExternalStorage::Initialize( for (auto& dir : external_dirs_) { app2ext_dir_details* dir_detail = reinterpret_cast( calloc(1, sizeof(app2ext_dir_details))); + if (!dir_detail) { + LOG(ERROR) << "Out of memory"; + g_list_free_full(glist, &ClearApp2ExtDirDetail); + return false; + } dir_detail->name = strdup(dir.c_str()); + if (!dir_detail->name) { + LOG(ERROR) << "Out of memory"; + free(dir_detail); + g_list_free_full(glist, &ClearApp2ExtDirDetail); + return false; + } dir_detail->type = APP2EXT_DIR_RO; glist = g_list_append(glist, dir_detail); } @@ -213,12 +232,7 @@ bool ExternalStorage::Initialize( assert(false && "Invalid installation mode"); } - g_list_free_full(glist, [](gpointer data) { - app2ext_dir_details* dir_detail = - reinterpret_cast(data); - free(dir_detail->name); - free(dir_detail); - }); + g_list_free_full(glist, &ClearApp2ExtDirDetail); return ret == 0; } diff --git a/src/common/plugins/types/category_plugin.cc b/src/common/plugins/types/category_plugin.cc index f53b7dd..d6c7a18 100644 --- a/src/common/plugins/types/category_plugin.cc +++ b/src/common/plugins/types/category_plugin.cc @@ -68,7 +68,18 @@ bool CategoryPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest, if (std::string(category).find(sub_key_prefix) == 0) { __category_t* c = reinterpret_cast<__category_t*>( calloc(1, sizeof(__category_t))); + if (!c) { + LOG(ERROR) << "Out of memory"; + g_list_free_full(category_list, &ClearCategoryDetail); + return false; + } c->name = strdup(category); + if (!c->name) { + LOG(ERROR) << "Out of memory"; + free(c); + g_list_free_full(category_list, &ClearCategoryDetail); + return false; + } category_list = g_list_append(category_list, c); } } diff --git a/src/common/plugins/types/metadata_plugin.cc b/src/common/plugins/types/metadata_plugin.cc index 25e495d..1ea1699 100644 --- a/src/common/plugins/types/metadata_plugin.cc +++ b/src/common/plugins/types/metadata_plugin.cc @@ -18,8 +18,10 @@ std::string GetMetadataTag(const std::string& url) { void ClearMetadataDetail(gpointer data) { __metadata_t* meta = reinterpret_cast<__metadata_t*>(data); - free(const_cast(meta->key)); - free(const_cast(meta->value)); + if (meta->key) + free(const_cast(meta->key)); + if (meta->value) + free(const_cast(meta->value)); free(meta); } @@ -70,8 +72,25 @@ bool MetadataPlugin::Run(xmlDocPtr /*doc_ptr*/, manifest_x* manifest, std::string(meta->key).find(sub_key_prefix) == 0) { __metadata_t* md = reinterpret_cast<__metadata_t*>( calloc(1, sizeof(__metadata_t))); + if (!md) { + LOG(ERROR) << "Out of memory"; + g_list_free_full(md_list, &ClearMetadataDetail); + return false; + } md->key = strdup(meta->key); + if (!md->key) { + LOG(ERROR) << "Out of memory"; + free(md); + g_list_free_full(md_list, &ClearMetadataDetail); + return false; + } md->value = strdup(meta->value); + if (!md->value) { + LOG(ERROR) << "Out of memory"; + ClearMetadataDetail(md); + g_list_free_full(md_list, &ClearMetadataDetail); + return false; + } md_list = g_list_append(md_list, md); } } diff --git a/src/common/privileges.cc b/src/common/privileges.cc index 16aee1a..4c0b0a8 100644 --- a/src/common/privileges.cc +++ b/src/common/privileges.cc @@ -4,6 +4,8 @@ #include "common/privileges.h" +#include + #include #include @@ -46,8 +48,25 @@ GList* PrivilegeToPrivilegeX(GList* privileges, const std::string& type) { for (auto& r : GListRange(privileges)) { privilege_x* privilege = reinterpret_cast(calloc(1, sizeof(privilege_x))); + if (!privilege) { + LOG(ERROR) << "Out of memory"; + g_list_free_full(result, &FreePrivilegeX); + return nullptr; + } privilege->type = strdup(type.c_str()); + if (!privilege->type) { + LOG(ERROR) << "Out of memory"; + FreePrivilegeX(privilege); + g_list_free_full(result, &FreePrivilegeX); + return nullptr; + } privilege->value = strdup(r); + if (!privilege->value) { + LOG(ERROR) << "Out of memory"; + FreePrivilegeX(privilege); + g_list_free_full(result, &FreePrivilegeX); + return nullptr; + } result = g_list_append(result, privilege); } return result; diff --git a/src/common/step/configuration/step_parse_manifest.cc b/src/common/step/configuration/step_parse_manifest.cc index 8f2a9d2..a445b39 100644 --- a/src/common/step/configuration/step_parse_manifest.cc +++ b/src/common/step/configuration/step_parse_manifest.cc @@ -248,6 +248,10 @@ bool StepParseManifest::FillPackageInfo(manifest_x* manifest) { for (auto& pair : pkg_info->labels()) { label_x* label = reinterpret_cast(calloc(1, sizeof(label_x))); + if (!label) { + LOG(ERROR) << "Out of memory"; + return false; + } if (!pair.first.empty()) label->lang = strdup(pair.first.c_str()); else @@ -295,6 +299,10 @@ bool StepParseManifest::FillAuthorInfo(manifest_x* manifest) { return true; author_x* author = reinterpret_cast(calloc(1, sizeof(author_x))); + if (!author) { + LOG(ERROR) << "Out of memory"; + return false; + } author->text = strdup(author_info->name().c_str()); author->email = strdup(author_info->email().c_str()); author->href = strdup(author_info->href().c_str()); @@ -314,6 +322,10 @@ bool StepParseManifest::FillDescriptionInfo(manifest_x* manifest) { for (auto& desc : description_info->descriptions) { description_x* description = reinterpret_cast (calloc(1, sizeof(description_x))); + if (!description) { + LOG(ERROR) << "Out of memory"; + return false; + } description->text = strdup(desc.description().c_str()); description->lang = !desc.xml_lang().empty() ? strdup(desc.xml_lang().c_str()) : strdup(DEFAULT_LOCALE); @@ -333,6 +345,10 @@ bool StepParseManifest::FillPrivileges(manifest_x* manifest) { for (auto& priv : privileges) { privilege_x* privilege = reinterpret_cast(calloc(1, sizeof(privilege_x))); + if (!privilege) { + LOG(ERROR) << "Out of memory"; + return false; + } privilege->value = strdup(priv.first.c_str()); privilege->type = strdup(priv.second.c_str()); manifest->privileges = g_list_append(manifest->privileges, privilege); @@ -415,6 +431,10 @@ bool StepParseManifest::FillWidgetApplication(manifest_x* manifest) { application_x* widget_app = static_cast(calloc(1, sizeof(application_x))); + if (!widget_app) { + LOG(ERROR) << "Out of memory"; + return false; + } widget_app->appid = strdup(application.app_info.appid().c_str()); widget_app->launch_mode = strdup(application.app_info.launch_mode().c_str()); @@ -480,6 +500,10 @@ bool StepParseManifest::FillServiceApplication(manifest_x* manifest) { application_x* service_app = static_cast(calloc(1, sizeof(application_x))); + if (!service_app) { + LOG(ERROR) << "Out of memory"; + return false; + } service_app->appid = strdup(application.app_info.appid().c_str()); service_app->multiple = strdup(application.app_info.multiple().c_str()); service_app->taskmanage = strdup(application.app_info.taskmanage().c_str()); @@ -549,6 +573,10 @@ bool StepParseManifest::FillUIApplication(manifest_x* manifest) { application_x* ui_app = static_cast(calloc(1, sizeof(application_x))); + if (!ui_app) { + LOG(ERROR) << "Out of memory"; + return false; + } ui_app->appid = strdup(application.app_info.appid().c_str()); ui_app->launch_mode = strdup(application.app_info.launch_mode().c_str()); ui_app->multiple = strdup(application.app_info.multiple().c_str()); @@ -643,6 +671,10 @@ bool StepParseManifest::FillWatchApplication(manifest_x* manifest) { application_x* watch_app = static_cast(calloc(1, sizeof(application_x))); + if (!watch_app) { + LOG(ERROR) << "Out of memory"; + return false; + } watch_app->appid = strdup(watch_application.app_info.appid().c_str()); if (bf::path(watch_application.app_info.exec().c_str()).is_absolute()) @@ -746,6 +778,10 @@ bool StepParseManifest::FillAppControl(application_x* app, for (const auto& control : app_control_list) { appcontrol_x* app_control = static_cast(calloc(1, sizeof(appcontrol_x))); + if (!app_control) { + LOG(ERROR) << "Out of memory"; + return false; + } app_control->operation = strdup(control.operation().c_str()); if (!control.mime().empty()) app_control->mime = strdup(control.mime().c_str()); @@ -769,6 +805,10 @@ bool StepParseManifest::FillDataControl(application_x* app, for (const auto& control : data_control_list) { datacontrol_x* data_control = static_cast(calloc(1, sizeof(datacontrol_x))); + if (!data_control) { + LOG(ERROR) << "Out of memory"; + return false; + } data_control->access = strdup(control.access().c_str()); data_control->providerid = strdup(control.providerid().c_str()); data_control->type = strdup(control.type().c_str()); @@ -789,7 +829,11 @@ template bool StepParseManifest::FillApplicationIconPaths(application_x* app, const T& icons_info) { for (auto& application_icon : icons_info.icons()) { - icon_x* icon = reinterpret_cast (calloc(1, sizeof(icon_x))); + icon_x* icon = reinterpret_cast(calloc(1, sizeof(icon_x))); + if (!icon) { + LOG(ERROR) << "Out of memory"; + return false; + } bf::path text; if (bf::path(application_icon.path()).is_absolute()) { text = application_icon.path(); @@ -821,6 +865,10 @@ bool StepParseManifest::FillLabel(application_x* app, const T& label_list) { for (const auto& control : label_list) { label_x* label = static_cast(calloc(1, sizeof(label_x))); + if (!label) { + LOG(ERROR) << "Out of memory"; + return false; + } // NOTE: name is an attribute, but the xml writer uses it as text. // This must be fixed in whole app-installer modules, including wgt. // Current implementation is just for compatibility. @@ -842,6 +890,10 @@ bool StepParseManifest::FillMetadata(application_x* app, for (auto& meta : meta_data_list) { metadata_x* metadata = static_cast(calloc(1, sizeof(metadata_x))); + if (!metadata) { + LOG(ERROR) << "Out of memory"; + return false; + } metadata->key = strdup(meta.key().c_str()); metadata->value = strdup(meta.val().c_str()); app->metadata = g_list_append(app->metadata, metadata); @@ -867,6 +919,10 @@ void StepParseManifest::AppendSplashScreen(application_x* app, const std::string& operation, const std::string& color_depth) { splashscreen_x* splashscreen = static_cast(calloc(1, sizeof(splashscreen_x))); + if (!splashscreen) { + LOG(ERROR) << "Out of memory"; + return; + } if (bf::path(src).is_absolute()) { splashscreen->src = strdup(src.c_str()); } else { @@ -965,6 +1021,10 @@ bool StepParseManifest::FillImage(application_x* app, for (auto& app_image : image_list.images) { image_x* image = static_cast(calloc(1, sizeof(image_x))); + if (!image) { + LOG(ERROR) << "Out of memory"; + return false; + } const std::string& lang = app_image.lang(); if (!lang.empty()) image->lang = strdup(lang.c_str()); @@ -1093,6 +1153,10 @@ Step::Status StepParseManifest::process() { manifest_x* manifest = static_cast(calloc(1, sizeof(manifest_x))); + if (!manifest) { + LOG(ERROR) << "Out of memory"; + return Step::Status::ERROR; + } if (!FillManifestX(const_cast(manifest))) { LOG(ERROR) << "[Parse] Storing manifest_x failed. " diff --git a/src/common/step/security/step_privilege_compatibility.cc b/src/common/step/security/step_privilege_compatibility.cc index 7748edd..3a2029a 100644 --- a/src/common/step/security/step_privilege_compatibility.cc +++ b/src/common/step/security/step_privilege_compatibility.cc @@ -130,6 +130,10 @@ Step::Status StepPrivilegeCompatibility::process() { internal_priv_type_ == InternalPrivType::BOTH) { privilege_x* privilege = reinterpret_cast(calloc(1, sizeof(privilege_x))); + if (!privilege) { + LOG(ERROR) << "Out of memory"; + return Step::Status::ERROR; + } privilege->type = strdup(kNativePrivilegeType); privilege->value = strdup(internal_priv.c_str()); context_->manifest_data.get()->privileges = @@ -140,6 +144,10 @@ Step::Status StepPrivilegeCompatibility::process() { internal_priv_type_ == InternalPrivType::BOTH) { privilege_x* privilege = reinterpret_cast(calloc(1, sizeof(privilege_x))); + if (!privilege) { + LOG(ERROR) << "Out of memory"; + return Step::Status::ERROR; + } privilege->type = strdup(kWebPrivilegeType); privilege->value = strdup(internal_priv.c_str()); context_->manifest_data.get()->privileges = @@ -149,6 +157,10 @@ Step::Status StepPrivilegeCompatibility::process() { if (context_->debug_mode.get()) { privilege_x* privilege = reinterpret_cast(calloc(1, sizeof(privilege_x))); + if (!privilege) { + LOG(ERROR) << "Out of memory"; + return Step::Status::ERROR; + } privilege->type = internal_priv_type_ == InternalPrivType::TPK ? strdup(kNativePrivilegeType) : strdup(kWebPrivilegeType); privilege->value = strdup(kAppDebuggingPrivilegeStr); -- 2.7.4