!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/libziparchive/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 <fstream>
#include <iomanip>
#include "utils/logger.h"
namespace panda::verifier {
@ -31,4 +32,29 @@ void GenerateModifiedAbc(const std::vector<unsigned char> &buffer, const std::st
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

View File

@ -18,9 +18,12 @@
#include <vector>
#include <string>
#include <unordered_map>
namespace panda::verifier {
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
#endif

View File

@ -15,9 +15,11 @@
#include "verifier.h"
#include <algorithm>
#include <cstdlib>
#include <gtest/gtest.h>
#include <string>
#include <unordered_map>
#include "file.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)
{
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};
ver.CollectIdInfos();
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);
EXPECT_TRUE(base_file.is_open());
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
unsigned char new_tag = 0x5c; // a invalid tag
for (size_t i = literal_id; i < buffer.size(); ++i) {
if (buffer[i] == tag) {
buffer[i] = new_tag;
break;
}
for (const auto &literal_id : literal_ids) {
size_t tag_off = static_cast<size_t>(literal_id) + sizeof(uint32_t);
buffer[tag_off] = invalid_tag;
}
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)
{
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};
ver.CollectIdInfos();
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);
EXPECT_TRUE(base_file.is_open());
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {});
size_t literal_id = 0x578; // The known literal_id in the abc file
// 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;
}
}
ModifyBuffer(inner_literal_map, buffer);
const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_010.abc";
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)
{
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};
ver.CollectIdInfos();
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);
EXPECT_TRUE(base_file.is_open());
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {});
size_t literal_id = 0x57a; // The known literal_id in the abc file
// 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;
}
}
ModifyBuffer(inner_method_map, buffer);
const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_011.abc";
GenerateModifiedAbc(buffer, target_file_name);

View File

@ -51,7 +51,7 @@ void Verifier::CollectIdInfos()
}
GetMethodIds();
GetLiteralIds();
CheckConstantPool(verifier::ActionType::COLLECTMETHODIDS);
CheckConstantPool(verifier::ActionType::COLLECTINFOS);
}
bool Verifier::VerifyChecksum()
@ -182,8 +182,8 @@ bool Verifier::CheckConstantPoolActions(const verifier::ActionType type, panda_f
case verifier::ActionType::CHECKCONSTPOOLCONTENT: {
return CheckConstantPoolMethodContent(method_id);
}
case verifier::ActionType::COLLECTMETHODIDS: {
if (!std::binary_search(method_ids_.begin(), method_ids_.end(), method_id)) {
case verifier::ActionType::COLLECTINFOS: {
if (std::find(method_ids_.begin(), method_ids_.end(), method_id) == method_ids_.end()) {
method_ids_.emplace_back(method_id);
}
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)
{
const auto class_idx = file_->GetClasses();
@ -214,6 +223,11 @@ bool Verifier::CheckConstantPool(const verifier::ActionType type)
if (!check_res) {
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::FLOAT:
case panda_file::LiteralTag::GETTER:
case panda_file::LiteralTag::SETTER:
case panda_file::LiteralTag::GENERATORMETHOD:
case panda_file::LiteralTag::LITERALBUFFERINDEX:
case panda_file::LiteralTag::ASYNCGENERATORMETHOD: {
@ -388,6 +404,7 @@ bool Verifier::VerifySingleLiteralArray(const panda_file::File::EntityId &litera
}
case panda_file::LiteralTag::METHOD: {
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)) {
return false;
}
@ -395,6 +412,7 @@ bool Verifier::VerifySingleLiteralArray(const panda_file::File::EntityId &litera
}
case panda_file::LiteralTag::LITERALARRAY: {
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)) {
return false;
}
@ -409,11 +427,16 @@ bool Verifier::VerifySingleLiteralArray(const panda_file::File::EntityId &litera
return true;
}
bool Verifier::IsModuleLiteralId(const panda_file::File::EntityId &id) const
{
return module_literals_.find(id.GetOffset()) != module_literals_.end();
}
bool Verifier::VerifyLiteralArrays()
{
for (const auto &arg_literal_id : literal_ids_) {
const auto literal_id = panda_file::File::EntityId(arg_literal_id);
if (!VerifySingleLiteralArray(literal_id)) {
if (!IsModuleLiteralId(literal_id) && !VerifySingleLiteralArray(literal_id)) {
return false;
}
}

View File

@ -17,6 +17,8 @@
#define VERIFIER_VERIFIER_H
#include <string>
#include <unordered_map>
#include <unordered_set>
#include "bytecode_instruction_enum_gen.h"
#include "bytecode_instruction-inl.h"
@ -35,7 +37,7 @@ enum class ActionType {
CHECKCONSTPOOL,
CHECKCONSTPOOLIDX,
CHECKCONSTPOOLCONTENT,
COLLECTMETHODIDS,
COLLECTINFOS,
};
class Verifier {
@ -50,9 +52,15 @@ public:
bool VerifyRegisterIndex();
bool VerifyConstantPoolIndex();
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:
void GetMethodIds();
void GetLiteralIds();
void CollectModuleLiteralId(const panda_file::File::EntityId &field_id);
bool CheckConstantPool(verifier::ActionType type);
size_t GetVRegCount(const BytecodeInstruction &bc_ins);
bool CheckConstantPoolActions(const verifier::ActionType type, panda_file::File::EntityId method_id);
@ -65,6 +73,7 @@ private:
bool VerifyMethodIdInLiteralArray(const uint32_t &id);
bool VerifyStringIdInLiteralArray(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 VerifyLiteralArrays();
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::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 uint32_t FILE_CONTENT_OFFSET = 12U;
};