From a1863f55ffaed091bbb1ef975d66eff0fb815b67 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 5 Aug 2020 10:30:24 +0900 Subject: [PATCH] Fix wrong implementation about encoding & decoding bundle raw bundle_encode_raw() must not use g_base64_encode(). This patch removes calling g_base64_encode() from bundle_encode_raw(). Change-Id: Iddedfb6a566e4b1d41052ec2e322c5312d2a0a52 Signed-off-by: Hwankyu Jhun --- include/bundle_cpp.h | 5 ++-- src/bundle-internal.cc | 60 +++++++++++++++++++++++++++------------ src/bundle-internal.h | 2 ++ src/bundle_cpp.cc | 15 +++++++--- src/stub.cc | 32 +++++++++++++++++++-- unit_tests/src/test_bundle.cc | 2 +- unit_tests/src/test_bundle_cpp.cc | 8 ++++-- 7 files changed, 95 insertions(+), 29 deletions(-) diff --git a/include/bundle_cpp.h b/include/bundle_cpp.h index 241fa98..6db29e4 100644 --- a/include/bundle_cpp.h +++ b/include/bundle_cpp.h @@ -139,7 +139,7 @@ class EXPORT_API Bundle final { * @since_tizen 5.5 * @param[in] raw The object for BundleRaw */ - explicit Bundle(BundleRaw raw); + explicit Bundle(BundleRaw raw, bool base64 = true); /** * @brief Constructor. @@ -282,9 +282,10 @@ class EXPORT_API Bundle final { /** * @brief Converts this object to BundleRaw type. * @since_tizen 5.5 + * @param[in] base64 @c true, the BundleRaw will be encoded using base64-encoding. * @return The object of BundleRaw */ - BundleRaw ToRaw(); + BundleRaw ToRaw(bool base64 = true); /** * @brief Gets the count of keys. diff --git a/src/bundle-internal.cc b/src/bundle-internal.cc index 9c7b2ee..2298412 100644 --- a/src/bundle-internal.cc +++ b/src/bundle-internal.cc @@ -142,27 +142,18 @@ int Bundle::GetType(const std::string& key) { } unsigned char* Bundle::Encode() { - std::vector bytes; - for (const auto& key_info : list_) { - auto encoded_bytes = key_info->Encode(); - bytes.insert(bytes.end(), encoded_bytes.begin(), encoded_bytes.end()); + int size = 0; + unsigned char* raw; + try { + raw = EncodeRaw(&size); + } catch (Exception& e) { + THROW(e.GetErrorCode()); } - char* checksum = static_cast( - g_compute_checksum_for_string(G_CHECKSUM_MD5, - reinterpret_cast(&bytes[0]), - static_cast(bytes.size()))); - if (checksum == nullptr) - THROW(BUNDLE_ERROR_OUT_OF_MEMORY); - - std::unique_ptr ptr(checksum, std::free); - unsigned char* p = reinterpret_cast(checksum); - bytes.insert(bytes.begin(), p, p + CHECKSUM_LENGTH); - + std::unique_ptr raw_ptr(raw, std::free); char* encoded_data = reinterpret_cast( - g_base64_encode( - reinterpret_cast(&bytes[0]), - reinterpret_cast(bytes.size()))); + g_base64_encode(reinterpret_cast(raw), + static_cast(size))); if (encoded_data == nullptr) THROW(BUNDLE_ERROR_OUT_OF_MEMORY); @@ -182,11 +173,44 @@ int Bundle::Decode(unsigned char* raw, int size) { if (d_len_raw < CHECKSUM_LENGTH) return BUNDLE_ERROR_OUT_OF_MEMORY; + return DecodeRaw(d_str, d_len_raw); +} + +unsigned char* Bundle::EncodeRaw(int* size) { + std::vector bytes; + for (const auto& key_info : list_) { + auto encoded_bytes = key_info->Encode(); + bytes.insert(bytes.end(), encoded_bytes.begin(), encoded_bytes.end()); + } + + char* checksum = static_cast( + g_compute_checksum_for_string(G_CHECKSUM_MD5, + reinterpret_cast(&bytes[0]), + static_cast(bytes.size()))); + if (checksum == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + std::unique_ptr ptr(checksum, std::free); + unsigned char* p = reinterpret_cast(checksum); + bytes.insert(bytes.begin(), p, p + CHECKSUM_LENGTH); + + unsigned char* raw = static_cast(malloc(bytes.size())); + if (raw == nullptr) + THROW(BUNDLE_ERROR_OUT_OF_MEMORY); + + std::copy(bytes.begin(), bytes.end(), raw); + *size = static_cast(bytes.size()); + return raw; +} + +int Bundle::DecodeRaw(unsigned char* raw, int size) { char* extract_checksum = new (std::nothrow) char[CHECKSUM_LENGTH + 1]; if (extract_checksum == nullptr) return BUNDLE_ERROR_OUT_OF_MEMORY; std::unique_ptr extract_ptr(extract_checksum); + unsigned char* d_str = raw; + unsigned int d_len_raw = size; strncpy(extract_checksum, reinterpret_cast(d_str), CHECKSUM_LENGTH); extract_checksum[CHECKSUM_LENGTH] = '\0'; diff --git a/src/bundle-internal.h b/src/bundle-internal.h index c79fed4..73f55d0 100644 --- a/src/bundle-internal.h +++ b/src/bundle-internal.h @@ -70,6 +70,8 @@ class Bundle { int GetType(const std::string& key); unsigned char* Encode(); + unsigned char* EncodeRaw(int* size); + int DecodeRaw(unsigned char* raw, int size); const std::map>& GetMap(); std::vector Export(); diff --git a/src/bundle_cpp.cc b/src/bundle_cpp.cc index f23f4d6..341dfce 100644 --- a/src/bundle_cpp.cc +++ b/src/bundle_cpp.cc @@ -38,9 +38,12 @@ Bundle::Bundle() throw std::bad_alloc(); } -Bundle::Bundle(BundleRaw raw) +Bundle::Bundle(BundleRaw raw, bool base64) : impl_(new Impl(this)) { - impl_->handle_ = bundle_decode(raw.first.get(), raw.second); + if (base64) + impl_->handle_ = bundle_decode(raw.first.get(), raw.second); + else + impl_->handle_ = bundle_decode_raw(raw.first.get(), raw.second); if (impl_->handle_ == nullptr) throw std::bad_alloc(); } @@ -257,10 +260,14 @@ std::vector Bundle::GetByte(const std::string& key) const { return std::vector(bytes, bytes + size); } -Bundle::BundleRaw Bundle::ToRaw() { +Bundle::BundleRaw Bundle::ToRaw(bool base64) { bundle_raw* raw = nullptr; int len = 0; - int ret = bundle_encode(impl_->handle_, &raw, &len); + int ret; + if (base64) + ret = bundle_encode(impl_->handle_, &raw, &len); + else + ret = bundle_encode_raw(impl_->handle_, &raw, &len); if (raw == nullptr) { LOGE("Fail to encode data (%d)", ret); throw std::bad_alloc(); diff --git a/src/stub.cc b/src/stub.cc index 3efcf95..7bf991a 100644 --- a/src/stub.cc +++ b/src/stub.cc @@ -350,12 +350,40 @@ extern "C" EXPORT_API bundle* bundle_decode(const bundle_raw* r, extern "C" EXPORT_API int bundle_encode_raw(bundle* b, bundle_raw** r, int* len) { - return bundle_encode(b, r, len); + if (b == nullptr || r == nullptr || len == nullptr) + return BUNDLE_ERROR_INVALID_PARAMETER; + + auto* h = reinterpret_cast(b); + try { + *r = reinterpret_cast(h->EncodeRaw(len)); + } catch (Exception& e) { + return e.GetErrorCode(); + } + return BUNDLE_ERROR_NONE; } extern "C" EXPORT_API bundle* bundle_decode_raw(const bundle_raw* r, const int data_size) { - return bundle_decode(r, data_size); + if (r == nullptr) { + set_last_result(BUNDLE_ERROR_INVALID_PARAMETER); + return nullptr; + } + + bundle* b = bundle_create(); + if (b == nullptr) + return nullptr; + + auto* h = reinterpret_cast(b); + auto* raw = const_cast(r); + int ret = h->DecodeRaw(static_cast(raw), data_size); + if (ret != BUNDLE_ERROR_NONE) { + bundle_free(b); + set_last_result(ret); + return nullptr; + } + + set_last_result(BUNDLE_ERROR_NONE); + return b; } extern "C" EXPORT_API int bundle_get_type(bundle* b, const char* key) { diff --git a/unit_tests/src/test_bundle.cc b/unit_tests/src/test_bundle.cc index 6bde750..9473c91 100644 --- a/unit_tests/src/test_bundle.cc +++ b/unit_tests/src/test_bundle.cc @@ -660,7 +660,7 @@ TEST_F(BundleTest, bundle_encode_raw_P) { ASSERT_NE(raw, nullptr); ASSERT_NE(len, 0); - bundle* decoded_b = bundle_decode(raw, len); + bundle* decoded_b = bundle_decode_raw(raw, len); std::unique_ptr b_ptr(decoded_b, bundle_free); ASSERT_EQ(get_last_result(), BUNDLE_ERROR_NONE); ASSERT_NE(decoded_b, nullptr); diff --git a/unit_tests/src/test_bundle_cpp.cc b/unit_tests/src/test_bundle_cpp.cc index 97ee62b..46fca50 100644 --- a/unit_tests/src/test_bundle_cpp.cc +++ b/unit_tests/src/test_bundle_cpp.cc @@ -81,8 +81,12 @@ TEST(Bundle, ToRaw) { Bundle bundle; bundle.Add("TestKey", "TestVal"); - auto r = bundle.ToRaw(); - Bundle b2(std::move(r)); + auto base64_r = bundle.ToRaw(); + Bundle b2(std::move(base64_r)); + EXPECT_EQ(bundle.GetString("TestKey"), "TestVal"); + + auto r = bundle.ToRaw(false); + Bundle b3(std::move(r), false); EXPECT_EQ(bundle.GetString("TestKey"), "TestVal"); } -- 2.7.4