Check raw data size 68/260668/3
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 1 Jul 2021 01:15:47 +0000 (10:15 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Fri, 2 Jul 2021 00:37:41 +0000 (09:37 +0900)
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 <h.jhun@samsung.com>
preference/backend-interface.hh
preference/file-backend-internal.cc
preference/file-backend-internal.hh
preference/file-internal.cc
preference/file-internal.hh
tool/preference_tool.cc

index f533307802a932a01af8b6ce47d873b796afbd87..76069bc48444c9085543eab2a5c3ab67cf93d77c 100644 (file)
@@ -32,7 +32,7 @@ class IBackend {
   virtual ~IBackend() { }
 
   virtual int Set(const Data& data) = 0;
-  virtual std::shared_ptr<Data> Get(const std::string& key) = 0;
+  virtual std::unique_ptr<Data> 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;
index b487da811be1a2f0ab4b4c9fbb1f3493bdb2fc9b..b3a2faa19e9c646582bfbfc1102089984a178493 100644 (file)
@@ -38,12 +38,12 @@ int FileBackend::Set(const Data& data) {
   return file.Write();
 }
 
-std::shared_ptr<Data> FileBackend::Get(const std::string& key) {
+std::unique_ptr<Data> FileBackend::Get(const std::string& key) {
   File file(key, false);
   if (file.Read() < 0)
     return nullptr;
 
-  return std::make_shared<Data>(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> data(file.GetData());
+  if (data.get() == nullptr)
+    return std::string("");
+
+  return data->GetKey();
 }
 
 }  // namespace internal
index 53f53f4fd7640e145daf3325f801c8dd91780da2..71b0d65edf1d6697ecda65004d7e79fa01a8befa 100644 (file)
@@ -33,7 +33,7 @@ class FileBackend : public IBackend {
   virtual ~FileBackend();
 
   int Set(const Data& data) override;
-  std::shared_ptr<Data> Get(const std::string& key) override;
+  std::unique_ptr<Data> 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;
index 6627aad24cdd9b93c47d0395c5d9085daa184c7a..71f627011738cef223ae22f576cf7e0b0a8df795 100644 (file)
@@ -80,44 +80,69 @@ void File::SetData(const Data& data) {
       std::back_inserter(raw_data_));
 }
 
-Data File::GetData() {
-  int index = 0;
+std::unique_ptr<Data> File::GetData() {
+  if (raw_data_.size() < sizeof(int))
+    return nullptr;
+
+  size_t index = 0;
   int key_length = 0;
   uint8_t* p = reinterpret_cast<uint8_t*>(&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<uint8_t*>(&type);
   std::copy(&raw_data_[index], &raw_data_[index] + sizeof(int), p);
   index += sizeof(int);
 
-  Data data(key);
+  auto data = std::make_unique<Data>(key);
+  if (data.get() == nullptr) {
+    _E("Out of memory");
+    return nullptr;
+  }
 
   Data::Type data_type = static_cast<Data::Type>(type);
   if (data_type == Data::Type::STRING) {
+    if (index == raw_data_.size())
+      return nullptr;
+
     const char* str = reinterpret_cast<const char*>(&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<uint8_t*>(&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<uint8_t*>(&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<uint8_t*>(&b);
     std::copy(&raw_data_[index], &raw_data_[index] + sizeof(bool), p);
-    data.SetBoolean(b);
+    data->SetBoolean(b);
   }
 
   return data;
index c455c2613f127c22d3a674478c4fe1c7fb439947..3d2183a3034f7ead0e3cc64532a212c3957db5f1 100644 (file)
@@ -52,7 +52,7 @@ class File {
   }
 
   void SetData(const Data& data);
-  Data GetData();
+  std::unique_ptr<Data> GetData();
 
   int Write();
   int Read();
index ceaa6dafef74850619c589182493e73c54f9f45a..d7d2cb90845b7d258cdb32b334fb049df1420981 100644 (file)
@@ -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