!786 Fix module literal problem in literal tag verification

Merge pull request !786 from OneYuan/module_literal
This commit is contained in:
openharmony_ci 2023-12-12 11:22:35 +00:00 committed by Gitee
commit 426ec9b91d
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
6 changed files with 82 additions and 41 deletions

View File

@ -317,6 +317,7 @@ if (!ark_standalone_build) {
"$ark_root/libpandafile/tests:host_unittest", "$ark_root/libpandafile/tests:host_unittest",
"$ark_root/libziparchive/tests:host_unittest", "$ark_root/libziparchive/tests:host_unittest",
"$ark_root/platforms/tests:host_unittest", "$ark_root/platforms/tests:host_unittest",
"$ark_root/verifier/tests:host_unittest",
] ]
} }

View File

@ -15,6 +15,7 @@
#include "utils.h" #include "utils.h"
#include <fstream> #include <fstream>
#include <iomanip>
#include "utils/logger.h" #include "utils/logger.h"
namespace panda::verifier { namespace panda::verifier {
@ -31,4 +32,29 @@ void GenerateModifiedAbc(const std::vector<unsigned char> &buffer, const std::st
abc_file.close(); abc_file.close();
} }
void ConvertToLittleEndian(std::vector<unsigned char> &inner_id, const uint32_t &id)
{
std::vector<unsigned char> bytes;
for (int i = 0; i < sizeof(uint32_t); ++i) {
unsigned char byte = static_cast<unsigned char>((id >> (i * 8)) & 0xff);
inner_id.push_back(byte);
}
}
void ModifyBuffer(std::unordered_map<uint32_t, uint32_t> &literal_map, std::vector<unsigned char> &buffer)
{
for (const auto &literal : literal_map) {
size_t literal_id = literal.first;
std::vector<unsigned char> inner_id;
ConvertToLittleEndian(inner_id, literal.second);
for (size_t i = literal_id; i < buffer.size(); ++i) {
if (buffer[i] == inner_id[0] && buffer[i+1] == inner_id[1]) {
buffer[i] = buffer[i + 1];
buffer[i + 1] = buffer[i + 2];
break;
}
}
}
}
} // namespace panda::verifier } // namespace panda::verifier

View File

@ -18,9 +18,12 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <unordered_map>
namespace panda::verifier { namespace panda::verifier {
void GenerateModifiedAbc(const std::vector<unsigned char> &buffer, const std::string &filename); void GenerateModifiedAbc(const std::vector<unsigned char> &buffer, const std::string &filename);
void ConvertToLittleEndian(std::vector<unsigned char> &inner_literal_id, const uint32_t &id);
void ModifyBuffer(std::unordered_map<uint32_t, uint32_t> &inner_literal_map, std::vector<unsigned char> &buffer);
} // namespace panda::verifier } // namespace panda::verifier
#endif #endif

View File

@ -15,9 +15,11 @@
#include "verifier.h" #include "verifier.h"
#include <algorithm>
#include <cstdlib> #include <cstdlib>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <string> #include <string>
#include <unordered_map>
#include "file.h" #include "file.h"
#include "utils.h" #include "utils.h"
@ -299,26 +301,23 @@ HWTEST_F(VerifierConstantPool, verifier_constant_pool_007, TestSize.Level1)
HWTEST_F(VerifierConstantPool, verifier_constant_pool_008, TestSize.Level1) HWTEST_F(VerifierConstantPool, verifier_constant_pool_008, TestSize.Level1)
{ {
const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_constant_pool_content.abc"; const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_constant_pool_content.abc";
std::vector<uint32_t> literal_ids;
{ {
panda::verifier::Verifier ver {base_file_name}; panda::verifier::Verifier ver {base_file_name};
ver.CollectIdInfos(); ver.CollectIdInfos();
EXPECT_TRUE(ver.VerifyConstantPoolContent()); EXPECT_TRUE(ver.VerifyConstantPoolContent());
std::copy(ver.literal_ids_.begin(), ver.literal_ids_.end(), std::back_inserter(literal_ids));
} }
std::ifstream base_file(base_file_name, std::ios::binary); std::ifstream base_file(base_file_name, std::ios::binary);
EXPECT_TRUE(base_file.is_open()); EXPECT_TRUE(base_file.is_open());
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {});
size_t literal_id = 0x2f8; // The known literal_id in the abc file unsigned char invalid_tag = 0x5c; // a invalid tag
unsigned char tag = 0x05; // The literal tag of string in the abc file for (const auto &literal_id : literal_ids) {
unsigned char new_tag = 0x5c; // a invalid tag size_t tag_off = static_cast<size_t>(literal_id) + sizeof(uint32_t);
buffer[tag_off] = invalid_tag;
for (size_t i = literal_id; i < buffer.size(); ++i) {
if (buffer[i] == tag) {
buffer[i] = new_tag;
break;
}
} }
const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_008.abc"; const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_008.abc";
@ -383,29 +382,19 @@ HWTEST_F(VerifierConstantPool, verifier_constant_pool_009, TestSize.Level1)
HWTEST_F(VerifierConstantPool, verifier_constant_pool_010, TestSize.Level1) HWTEST_F(VerifierConstantPool, verifier_constant_pool_010, TestSize.Level1)
{ {
const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_literal_array.abc"; const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_literal_array.abc";
std::unordered_map<uint32_t, uint32_t> inner_literal_map;
{ {
panda::verifier::Verifier ver {base_file_name}; panda::verifier::Verifier ver {base_file_name};
ver.CollectIdInfos(); ver.CollectIdInfos();
EXPECT_TRUE(ver.VerifyConstantPoolContent()); EXPECT_TRUE(ver.VerifyConstantPoolContent());
inner_literal_map.insert(ver.inner_literal_map_.begin(), ver.inner_literal_map_.end());
} }
std::ifstream base_file(base_file_name, std::ios::binary); std::ifstream base_file(base_file_name, std::ios::binary);
EXPECT_TRUE(base_file.is_open()); EXPECT_TRUE(base_file.is_open());
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {});
size_t literal_id = 0x578; // The known literal_id in the abc file ModifyBuffer(inner_literal_map, buffer);
// The known literal_id in the literal array of the abc file
std::vector<unsigned char> inner_literal_id = {0xe9, 0x04};
std::vector<unsigned char> new_literal_id = {0xaa, 0xaa};
for (size_t i = literal_id; i < buffer.size(); ++i) {
if (buffer[i] == inner_literal_id[0] && buffer[i+1] == inner_literal_id[1]) {
buffer[i] = new_literal_id[0];
buffer[i + 1] = new_literal_id[1];
break;
}
}
const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_010.abc"; const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_010.abc";
GenerateModifiedAbc(buffer, target_file_name); GenerateModifiedAbc(buffer, target_file_name);
@ -427,29 +416,19 @@ HWTEST_F(VerifierConstantPool, verifier_constant_pool_010, TestSize.Level1)
HWTEST_F(VerifierConstantPool, verifier_constant_pool_011, TestSize.Level1) HWTEST_F(VerifierConstantPool, verifier_constant_pool_011, TestSize.Level1)
{ {
const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_literal_array.abc"; const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_literal_array.abc";
std::unordered_map<uint32_t, uint32_t> inner_method_map;
{ {
panda::verifier::Verifier ver {base_file_name}; panda::verifier::Verifier ver {base_file_name};
ver.CollectIdInfos(); ver.CollectIdInfos();
EXPECT_TRUE(ver.VerifyConstantPoolContent()); EXPECT_TRUE(ver.VerifyConstantPoolContent());
inner_method_map.insert(ver.inner_method_map_.begin(), ver.inner_method_map_.end());
} }
std::ifstream base_file(base_file_name, std::ios::binary); std::ifstream base_file(base_file_name, std::ios::binary);
EXPECT_TRUE(base_file.is_open()); EXPECT_TRUE(base_file.is_open());
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {});
size_t literal_id = 0x57a; // The known literal_id in the abc file ModifyBuffer(inner_method_map, buffer);
// The known method_id in the literal array of the abc file
std::vector<unsigned char> method_id = {0xcc, 0x02};
std::vector<unsigned char> new_method_id = {0xff, 0xff};
for (size_t i = literal_id; i < buffer.size(); ++i) {
if (buffer[i] == method_id[0] && buffer[i+1] == method_id[1]) {
buffer[i] = new_method_id[0];
buffer[i + 1] = new_method_id[1];
break;
}
}
const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_011.abc"; const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_011.abc";
GenerateModifiedAbc(buffer, target_file_name); GenerateModifiedAbc(buffer, target_file_name);

View File

@ -51,7 +51,7 @@ void Verifier::CollectIdInfos()
} }
GetMethodIds(); GetMethodIds();
GetLiteralIds(); GetLiteralIds();
CheckConstantPool(verifier::ActionType::COLLECTMETHODIDS); CheckConstantPool(verifier::ActionType::COLLECTINFOS);
} }
bool Verifier::VerifyChecksum() bool Verifier::VerifyChecksum()
@ -182,8 +182,8 @@ bool Verifier::CheckConstantPoolActions(const verifier::ActionType type, panda_f
case verifier::ActionType::CHECKCONSTPOOLCONTENT: { case verifier::ActionType::CHECKCONSTPOOLCONTENT: {
return CheckConstantPoolMethodContent(method_id); return CheckConstantPoolMethodContent(method_id);
} }
case verifier::ActionType::COLLECTMETHODIDS: { case verifier::ActionType::COLLECTINFOS: {
if (!std::binary_search(method_ids_.begin(), method_ids_.end(), method_id)) { if (std::find(method_ids_.begin(), method_ids_.end(), method_id) == method_ids_.end()) {
method_ids_.emplace_back(method_id); method_ids_.emplace_back(method_id);
} }
return true; return true;
@ -194,6 +194,15 @@ bool Verifier::CheckConstantPoolActions(const verifier::ActionType type, panda_f
} }
} }
void Verifier::CollectModuleLiteralId(const panda_file::File::EntityId &field_id)
{
panda_file::FieldDataAccessor field_accessor(*file_, field_id);
const auto literal_id = field_accessor.GetValue<uint32_t>().value();
if (std::find(literal_ids_.begin(), literal_ids_.end(), literal_id) != literal_ids_.end()) {
module_literals_.insert(literal_id);
}
}
bool Verifier::CheckConstantPool(const verifier::ActionType type) bool Verifier::CheckConstantPool(const verifier::ActionType type)
{ {
const auto class_idx = file_->GetClasses(); const auto class_idx = file_->GetClasses();
@ -214,6 +223,11 @@ bool Verifier::CheckConstantPool(const verifier::ActionType type)
if (!check_res) { if (!check_res) {
return false; return false;
} }
if (type == verifier::ActionType::COLLECTINFOS) {
class_accessor.EnumerateFields([&](panda_file::FieldDataAccessor &field_accessor) -> void {
CollectModuleLiteralId(field_accessor.GetFieldId());
});
}
} }
} }
@ -354,6 +368,8 @@ bool Verifier::VerifySingleLiteralArray(const panda_file::File::EntityId &litera
} }
case panda_file::LiteralTag::INTEGER: case panda_file::LiteralTag::INTEGER:
case panda_file::LiteralTag::FLOAT: case panda_file::LiteralTag::FLOAT:
case panda_file::LiteralTag::GETTER:
case panda_file::LiteralTag::SETTER:
case panda_file::LiteralTag::GENERATORMETHOD: case panda_file::LiteralTag::GENERATORMETHOD:
case panda_file::LiteralTag::LITERALBUFFERINDEX: case panda_file::LiteralTag::LITERALBUFFERINDEX:
case panda_file::LiteralTag::ASYNCGENERATORMETHOD: { case panda_file::LiteralTag::ASYNCGENERATORMETHOD: {
@ -388,6 +404,7 @@ bool Verifier::VerifySingleLiteralArray(const panda_file::File::EntityId &litera
} }
case panda_file::LiteralTag::METHOD: { case panda_file::LiteralTag::METHOD: {
const auto value = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp)); const auto value = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
inner_method_map_.emplace(literal_id.GetOffset(), value);
if (!VerifyMethodIdInLiteralArray(value)) { if (!VerifyMethodIdInLiteralArray(value)) {
return false; return false;
} }
@ -395,6 +412,7 @@ bool Verifier::VerifySingleLiteralArray(const panda_file::File::EntityId &litera
} }
case panda_file::LiteralTag::LITERALARRAY: { case panda_file::LiteralTag::LITERALARRAY: {
const auto value = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp)); const auto value = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint32_t)>(&sp));
inner_literal_map_.emplace(literal_id.GetOffset(), value);
if (!VerifyLiteralIdInLiteralArray(value)) { if (!VerifyLiteralIdInLiteralArray(value)) {
return false; return false;
} }
@ -409,11 +427,16 @@ bool Verifier::VerifySingleLiteralArray(const panda_file::File::EntityId &litera
return true; return true;
} }
bool Verifier::IsModuleLiteralId(const panda_file::File::EntityId &id) const
{
return module_literals_.find(id.GetOffset()) != module_literals_.end();
}
bool Verifier::VerifyLiteralArrays() bool Verifier::VerifyLiteralArrays()
{ {
for (const auto &arg_literal_id : literal_ids_) { for (const auto &arg_literal_id : literal_ids_) {
const auto literal_id = panda_file::File::EntityId(arg_literal_id); const auto literal_id = panda_file::File::EntityId(arg_literal_id);
if (!VerifySingleLiteralArray(literal_id)) { if (!IsModuleLiteralId(literal_id) && !VerifySingleLiteralArray(literal_id)) {
return false; return false;
} }
} }

View File

@ -17,6 +17,8 @@
#define VERIFIER_VERIFIER_H #define VERIFIER_VERIFIER_H
#include <string> #include <string>
#include <unordered_map>
#include <unordered_set>
#include "bytecode_instruction_enum_gen.h" #include "bytecode_instruction_enum_gen.h"
#include "bytecode_instruction-inl.h" #include "bytecode_instruction-inl.h"
@ -35,7 +37,7 @@ enum class ActionType {
CHECKCONSTPOOL, CHECKCONSTPOOL,
CHECKCONSTPOOLIDX, CHECKCONSTPOOLIDX,
CHECKCONSTPOOLCONTENT, CHECKCONSTPOOLCONTENT,
COLLECTMETHODIDS, COLLECTINFOS,
}; };
class Verifier { class Verifier {
@ -50,9 +52,15 @@ public:
bool VerifyRegisterIndex(); bool VerifyRegisterIndex();
bool VerifyConstantPoolIndex(); bool VerifyConstantPoolIndex();
bool VerifyConstantPoolContent(); bool VerifyConstantPoolContent();
std::vector<uint32_t> literal_ids_;
std::unordered_map<uint32_t, uint32_t> inner_literal_map_;
std::unordered_map<uint32_t, uint32_t> inner_method_map_;
private: private:
void GetMethodIds(); void GetMethodIds();
void GetLiteralIds(); void GetLiteralIds();
void CollectModuleLiteralId(const panda_file::File::EntityId &field_id);
bool CheckConstantPool(verifier::ActionType type); bool CheckConstantPool(verifier::ActionType type);
size_t GetVRegCount(const BytecodeInstruction &bc_ins); size_t GetVRegCount(const BytecodeInstruction &bc_ins);
bool CheckConstantPoolActions(const verifier::ActionType type, panda_file::File::EntityId method_id); bool CheckConstantPoolActions(const verifier::ActionType type, panda_file::File::EntityId method_id);
@ -65,6 +73,7 @@ private:
bool VerifyMethodIdInLiteralArray(const uint32_t &id); bool VerifyMethodIdInLiteralArray(const uint32_t &id);
bool VerifyStringIdInLiteralArray(const uint32_t &id); bool VerifyStringIdInLiteralArray(const uint32_t &id);
bool VerifyLiteralIdInLiteralArray(const uint32_t &id); bool VerifyLiteralIdInLiteralArray(const uint32_t &id);
bool IsModuleLiteralId(const panda_file::File::EntityId &id) const;
bool VerifySingleLiteralArray(const panda_file::File::EntityId &literal_id); bool VerifySingleLiteralArray(const panda_file::File::EntityId &literal_id);
bool VerifyLiteralArrays(); bool VerifyLiteralArrays();
bool VerifyStringId(const BytecodeInstruction &bc_ins, const panda_file::File::EntityId &method_id); bool VerifyStringId(const BytecodeInstruction &bc_ins, const panda_file::File::EntityId &method_id);
@ -80,7 +89,7 @@ private:
std::unique_ptr<const panda_file::File> file_; std::unique_ptr<const panda_file::File> file_;
std::vector<panda_file::File::EntityId> method_ids_; std::vector<panda_file::File::EntityId> method_ids_;
std::vector<uint32_t> literal_ids_; std::unordered_set<uint32_t> module_literals_;
static constexpr size_t DEFAULT_ARGUMENT_NUMBER = 3; static constexpr size_t DEFAULT_ARGUMENT_NUMBER = 3;
static constexpr uint32_t FILE_CONTENT_OFFSET = 12U; static constexpr uint32_t FILE_CONTENT_OFFSET = 12U;
}; };