From: Hwankyu Jhun Date: Thu, 1 Jul 2021 01:15:47 +0000 (+0900) Subject: Check raw data size X-Git-Tag: submit/tizen/20210702.005440~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=92cde7a2b229ff7872865c7f92f88b3b17f0b998;p=platform%2Fcore%2Fapi%2Fpreference.git Check raw data size If the device was turned off when the application was writing the preference data, the data can be corrupted. If the data is corrupted, the application will be crashed when reading the data. To prevent crash issue, this patch adds to check whether the size of the raw data is valid or not. Change-Id: I09379f294104200aa0fc4d3799ddc2a56a96745b Signed-off-by: Hwankyu Jhun --- diff --git a/preference/backend-interface.hh b/preference/backend-interface.hh index f533307..76069bc 100644 --- a/preference/backend-interface.hh +++ b/preference/backend-interface.hh @@ -32,7 +32,7 @@ class IBackend { virtual ~IBackend() { } virtual int Set(const Data& data) = 0; - virtual std::shared_ptr Get(const std::string& key) = 0; + virtual std::unique_ptr Get(const std::string& key) = 0; virtual int Remove(const std::string& key) = 0; virtual int RemoveAll() = 0; virtual int AddWatch(const std::string& key, IDataEvent* listener) = 0; diff --git a/preference/file-backend-internal.cc b/preference/file-backend-internal.cc index b487da8..b3a2faa 100644 --- a/preference/file-backend-internal.cc +++ b/preference/file-backend-internal.cc @@ -38,12 +38,12 @@ int FileBackend::Set(const Data& data) { return file.Write(); } -std::shared_ptr FileBackend::Get(const std::string& key) { +std::unique_ptr FileBackend::Get(const std::string& key) { File file(key, false); if (file.Read() < 0) return nullptr; - return std::make_shared(file.GetData()); + return file.GetData(); } int FileBackend::Remove(const std::string& key) { @@ -231,8 +231,11 @@ std::string FileBackend::GetKey(const std::string& file_name) { if (file.Read() < 0) return std::string(""); - auto data = file.GetData(); - return data.GetKey(); + std::unique_ptr data(file.GetData()); + if (data.get() == nullptr) + return std::string(""); + + return data->GetKey(); } } // namespace internal diff --git a/preference/file-backend-internal.hh b/preference/file-backend-internal.hh index 53f53f4..71b0d65 100644 --- a/preference/file-backend-internal.hh +++ b/preference/file-backend-internal.hh @@ -33,7 +33,7 @@ class FileBackend : public IBackend { virtual ~FileBackend(); int Set(const Data& data) override; - std::shared_ptr Get(const std::string& key) override; + std::unique_ptr Get(const std::string& key) override; int Remove(const std::string& key) override; int RemoveAll() override; int AddWatch(const std::string& key, IDataEvent* listener) override; diff --git a/preference/file-internal.cc b/preference/file-internal.cc index 6627aad..71f6270 100644 --- a/preference/file-internal.cc +++ b/preference/file-internal.cc @@ -80,44 +80,69 @@ void File::SetData(const Data& data) { std::back_inserter(raw_data_)); } -Data File::GetData() { - int index = 0; +std::unique_ptr File::GetData() { + if (raw_data_.size() < sizeof(int)) + return nullptr; + + size_t index = 0; int key_length = 0; uint8_t* p = reinterpret_cast(&key_length); std::copy(&raw_data_[index], &raw_data_[index] + sizeof(int), p); index += sizeof(int); + if (index + key_length > raw_data_.size()) + return nullptr; + std::string key; std::copy(&raw_data_[index], &raw_data_[index] + key_length, std::back_inserter(key)); index += key_length; + if (index + sizeof(int) > raw_data_.size()) + return nullptr; + int type = 0; p = reinterpret_cast(&type); std::copy(&raw_data_[index], &raw_data_[index] + sizeof(int), p); index += sizeof(int); - Data data(key); + auto data = std::make_unique(key); + if (data.get() == nullptr) { + _E("Out of memory"); + return nullptr; + } Data::Type data_type = static_cast(type); if (data_type == Data::Type::STRING) { + if (index == raw_data_.size()) + return nullptr; + const char* str = reinterpret_cast(&raw_data_[index]); - data.SetString(str); + data->SetString(str); } else if (data_type == Data::Type::INT) { + if (index + sizeof(int) > raw_data_.size()) + return nullptr; + int i = 0; p = reinterpret_cast(&i); std::copy(&raw_data_[index], &raw_data_[index] + sizeof(int), p); - data.SetInt(i); + data->SetInt(i); } else if (data_type == Data::Type::DOUBLE) { + if (index + sizeof(double) > raw_data_.size()) + return nullptr; + double d = 0; p = reinterpret_cast(&d); std::copy(&raw_data_[index], &raw_data_[index] + sizeof(double), p); - data.SetDouble(d); + data->SetDouble(d); } else if (data_type == Data::Type::BOOLEAN) { + if (index + sizeof(bool) > raw_data_.size()) + return nullptr; + bool b = 0; p = reinterpret_cast(&b); std::copy(&raw_data_[index], &raw_data_[index] + sizeof(bool), p); - data.SetBoolean(b); + data->SetBoolean(b); } return data; diff --git a/preference/file-internal.hh b/preference/file-internal.hh index c455c26..3d2183a 100644 --- a/preference/file-internal.hh +++ b/preference/file-internal.hh @@ -52,7 +52,7 @@ class File { } void SetData(const Data& data); - Data GetData(); + std::unique_ptr GetData(); int Write(); int Read(); diff --git a/tool/preference_tool.cc b/tool/preference_tool.cc index ceaa6da..d7d2cb9 100644 --- a/tool/preference_tool.cc +++ b/tool/preference_tool.cc @@ -61,7 +61,7 @@ class PrefTool { gid_t GetGid(const std::string& name); Data::Type ConvertType(const std::string& type); std::string GetTypeName(Data::Type type); - void PrintData(const Data& data); + void PrintData(const Data* data); }; PrefTool& PrefTool::GetInst() { @@ -161,8 +161,11 @@ void PrefTool::Get(const std::string& pkg_id, const std::string& key) { return; } - Data data = file.GetData(); - PrintData(data); + auto data = file.GetData(); + if (data.get() == nullptr) + return; + + PrintData(data.get()); } void PrefTool::Get(const std::string& pkg_id) { @@ -193,8 +196,9 @@ void PrefTool::Get(const std::string& pkg_id) { break; } - Data data = file.GetData(); - PrintData(data); + auto data = file.GetData(); + if (data.get() != nullptr) + PrintData(data.get()); } printf("=================================================================\n"); closedir(dp); @@ -358,18 +362,18 @@ std::string PrefTool::GetTypeName(Data::Type type) { return "none"; } -void PrefTool::PrintData(const Data& data) { - auto type = data.GetType(); +void PrefTool::PrintData(const Data* data) { + auto type = data->GetType(); printf("[key] %s [type] %s [value] ", - data.GetKey().c_str(), GetTypeName(type).c_str()); + data->GetKey().c_str(), GetTypeName(type).c_str()); if (type == Data::Type::STRING) - printf("%s\n", data.GetString()); + printf("%s\n", data->GetString()); else if (type == Data::Type::INT) - printf("%d\n", data.GetInt()); + printf("%d\n", data->GetInt()); else if (type == Data::Type::DOUBLE) - printf("%f\n", data.GetDouble()); + printf("%f\n", data->GetDouble()); else - printf("%s\n", data.GetBoolean() ? "true" : "false"); + printf("%s\n", data->GetBoolean() ? "true" : "false"); } } // namespace