1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "verifier.h" 17 18 #include <algorithm> 19 #include <cstdlib> 20 #include <gtest/gtest.h> 21 #include <string> 22 #include <unordered_map> 23 24 #include "file.h" 25 #include "utils.h" 26 27 using namespace testing::ext; 28 29 namespace panda::verifier { 30 class VerifierConstantPool : public testing::Test { 31 public: SetUpTestCase(void)32 static void SetUpTestCase(void) {}; TearDownTestCase(void)33 static void TearDownTestCase(void) {}; SetUp()34 void SetUp() {}; TearDown()35 void TearDown() {}; 36 }; 37 38 /** 39 * @tc.name: verifier_constant_pool_001 40 * @tc.desc: Verify abc file. 41 * @tc.type: FUNC 42 * @tc.require: file path and name 43 */ 44 HWTEST_F(VerifierConstantPool, verifier_constant_pool_001, TestSize.Level1) 45 { 46 const std::string file_name = GRAPH_TEST_ABC_DIR "test_constant_pool.abc"; 47 panda::verifier::Verifier ver {file_name}; 48 ver.CollectIdInfos(); 49 EXPECT_TRUE(ver.VerifyConstantPoolIndex()); 50 } 51 52 /** 53 * @tc.name: verifier_constant_pool_002 54 * @tc.desc: Verify the method id of the abc file. 55 * @tc.type: FUNC 56 * @tc.require: file path and name 57 */ 58 HWTEST_F(VerifierConstantPool, verifier_constant_pool_002, TestSize.Level1) 59 { 60 const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_constant_pool.abc"; 61 { 62 panda::verifier::Verifier ver {base_file_name}; 63 ver.CollectIdInfos(); 64 EXPECT_TRUE(ver.VerifyConstantPoolIndex()); 65 } 66 std::ifstream base_file(base_file_name, std::ios::binary); 67 EXPECT_TRUE(base_file.is_open()); 68 69 std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); 70 71 std::vector<uint8_t> new_method_id = {0x0c, 0x00}; // The known string id in the abc file 72 std::vector<uint8_t> method_id = {0x0e, 0x00}; // The known method id in the abc file 73 74 for (size_t i = buffer.size() - 1; i >= 0; --i) { 75 if (buffer[i] == method_id[0] && buffer[i + 1] == method_id[1]) { 76 buffer[i] = static_cast<unsigned char>(new_method_id[0]); 77 buffer[i + 1] = static_cast<unsigned char>(new_method_id[1]); 78 break; 79 } 80 } 81 82 const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_002.abc"; 83 GenerateModifiedAbc(buffer, target_file_name); 84 base_file.close(); 85 86 { 87 panda::verifier::Verifier ver {target_file_name}; 88 ver.CollectIdInfos(); 89 EXPECT_FALSE(ver.VerifyConstantPoolIndex()); 90 } 91 } 92 93 /** 94 * @tc.name: verifier_constant_pool_003 95 * @tc.desc: Verify the literal id of the abc file. 96 * @tc.type: FUNC 97 * @tc.require: file path and name 98 */ 99 HWTEST_F(VerifierConstantPool, verifier_constant_pool_003, TestSize.Level1) 100 { 101 const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_constant_pool.abc"; 102 { 103 panda::verifier::Verifier ver {base_file_name}; 104 ver.CollectIdInfos(); 105 EXPECT_TRUE(ver.VerifyConstantPoolIndex()); 106 } 107 std::ifstream base_file(base_file_name, std::ios::binary); 108 EXPECT_TRUE(base_file.is_open()); 109 110 std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); 111 112 std::vector<uint8_t> new_literal_id = {0x0e, 0x00}; // The known method id in the abc file 113 std::vector<uint8_t> literal_id = {0x0f, 0x00}; // The known literal id in the abc file 114 115 for (size_t i = 0; i < buffer.size(); ++i) { 116 if (buffer[i] == literal_id[0] && buffer[i + 1] == literal_id[1]) { 117 buffer[i] = static_cast<unsigned char>(new_literal_id[0]); 118 buffer[i + 1] = static_cast<unsigned char>(new_literal_id[1]); 119 break; 120 } 121 } 122 123 const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_003.abc"; 124 125 GenerateModifiedAbc(buffer, target_file_name); 126 127 base_file.close(); 128 129 { 130 panda::verifier::Verifier ver {target_file_name}; 131 ver.CollectIdInfos(); 132 EXPECT_FALSE(ver.VerifyConstantPoolIndex()); 133 } 134 } 135 136 /** 137 * @tc.name: verifier_constant_pool_004 138 * @tc.desc: Verify the string id of the abc file. 139 * @tc.type: FUNC 140 * @tc.require: file path and name 141 */ 142 HWTEST_F(VerifierConstantPool, verifier_constant_pool_004, TestSize.Level1) 143 { 144 const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_constant_pool.abc"; 145 { 146 panda::verifier::Verifier ver {base_file_name}; 147 ver.CollectIdInfos(); 148 EXPECT_TRUE(ver.VerifyConstantPoolIndex()); 149 } 150 std::ifstream base_file(base_file_name, std::ios::binary); 151 EXPECT_TRUE(base_file.is_open()); 152 153 std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); 154 155 std::vector<uint8_t> new_string_id = {0x0f, 0x00}; // The known literal id in the abc file 156 std::vector<uint8_t> string_id = {0x0c, 0x00}; // The known string id in the abc file 157 158 for (size_t i = sizeof(panda_file::File::Header); i < buffer.size(); ++i) { 159 if (buffer[i] == string_id[0] && buffer[i + 1] == string_id[1]) { 160 buffer[i] = static_cast<unsigned char>(new_string_id[0]); 161 buffer[i + 1] = static_cast<unsigned char>(new_string_id[1]); 162 break; 163 } 164 } 165 166 const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_004.abc"; 167 GenerateModifiedAbc(buffer, target_file_name); 168 base_file.close(); 169 170 { 171 panda::verifier::Verifier ver {target_file_name}; 172 ver.CollectIdInfos(); 173 EXPECT_FALSE(ver.VerifyConstantPoolIndex()); 174 } 175 } 176 177 /** 178 * @tc.name: verifier_constant_pool_006 179 * @tc.desc: Verify the format of the abc file. 180 * @tc.type: FUNC 181 * @tc.require: file path and name 182 */ 183 HWTEST_F(VerifierConstantPool, verifier_constant_pool_006, TestSize.Level1) 184 { 185 const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_constant_pool_content.abc"; 186 { 187 panda::verifier::Verifier ver {base_file_name}; 188 ver.CollectIdInfos(); 189 EXPECT_TRUE(ver.VerifyConstantPoolContent()); 190 } 191 std::ifstream base_file(base_file_name, std::ios::binary); 192 EXPECT_TRUE(base_file.is_open()); 193 194 std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); 195 196 unsigned char new_opcode = 0xff; 197 std::vector<unsigned char> opcode_imm8 = {0x4f, 0x13}; // The known instruction in the abc file 198 for (size_t i = 0; i < buffer.size() - opcode_imm8.size(); ++i) { 199 if (buffer[i] == opcode_imm8[0] && buffer[i + 1] == opcode_imm8[1]) { 200 buffer[i] = new_opcode; 201 break; 202 } 203 } 204 205 const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_006.abc"; 206 GenerateModifiedAbc(buffer, target_file_name); 207 base_file.close(); 208 209 { 210 panda::verifier::Verifier ver {target_file_name}; 211 ver.CollectIdInfos(); 212 EXPECT_FALSE(ver.VerifyConstantPoolContent()); 213 } 214 } 215 216 /** 217 * @tc.name: verifier_constant_pool_007 218 * @tc.desc: Verify the jump instruction of the abc file. 219 * @tc.type: FUNC 220 * @tc.require: file path and name 221 */ 222 HWTEST_F(VerifierConstantPool, verifier_constant_pool_007, TestSize.Level1) 223 { 224 const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_constant_pool_content.abc"; 225 { 226 panda::verifier::Verifier ver {base_file_name}; 227 ver.CollectIdInfos(); 228 EXPECT_TRUE(ver.VerifyConstantPoolContent()); 229 } 230 std::ifstream base_file(base_file_name, std::ios::binary); 231 EXPECT_TRUE(base_file.is_open()); 232 233 std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); 234 235 unsigned char new_imm8 = 0x4f; 236 std::vector<unsigned char> opcode_imm8 = {0x4f, 0x13}; // The known jump instruction in the abc file 237 for (size_t i = 0; i < buffer.size() - opcode_imm8.size(); ++i) { 238 if (buffer[i] == opcode_imm8[0] && buffer[i + 1] == opcode_imm8[1]) { 239 buffer[i + 1] = new_imm8; 240 break; 241 } 242 } 243 244 const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_007.abc"; 245 GenerateModifiedAbc(buffer, target_file_name); 246 base_file.close(); 247 248 { 249 panda::verifier::Verifier ver {target_file_name}; 250 ver.CollectIdInfos(); 251 EXPECT_FALSE(ver.VerifyConstantPoolContent()); 252 } 253 } 254 255 /** 256 * @tc.name: verifier_constant_pool_008 257 * @tc.desc: Verify the literal tag of the abc file. 258 * @tc.type: FUNC 259 * @tc.require: file path and name 260 */ 261 HWTEST_F(VerifierConstantPool, verifier_constant_pool_008, TestSize.Level1) 262 { 263 const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_constant_pool_content.abc"; 264 std::vector<uint32_t> literal_ids; 265 { 266 panda::verifier::Verifier ver {base_file_name}; 267 ver.CollectIdInfos(); 268 EXPECT_TRUE(ver.VerifyConstantPoolContent()); 269 std::copy(ver.literal_ids_.begin(), ver.literal_ids_.end(), std::back_inserter(literal_ids)); 270 } 271 std::ifstream base_file(base_file_name, std::ios::binary); 272 EXPECT_TRUE(base_file.is_open()); 273 274 std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); 275 276 unsigned char invalid_tag = 0x5c; // a invalid tag 277 278 for (const auto &literal_id : literal_ids) { 279 size_t tag_off = static_cast<size_t>(literal_id) + sizeof(uint32_t); 280 buffer[tag_off] = invalid_tag; 281 } 282 283 const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_008.abc"; 284 GenerateModifiedAbc(buffer, target_file_name); 285 base_file.close(); 286 287 { 288 panda::verifier::Verifier ver {target_file_name}; 289 ver.CollectIdInfos(); 290 EXPECT_FALSE(ver.VerifyConstantPoolContent()); 291 } 292 } 293 294 /** 295 * @tc.name: verifier_constant_pool_010 296 * @tc.desc: Verify the literal id in the literal array of the abc file. 297 * @tc.type: FUNC 298 * @tc.require: file path and name 299 */ 300 HWTEST_F(VerifierConstantPool, verifier_constant_pool_010, TestSize.Level1) 301 { 302 const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_literal_array.abc"; 303 std::unordered_map<uint32_t, uint32_t> inner_literal_map; 304 { 305 panda::verifier::Verifier ver {base_file_name}; 306 ver.CollectIdInfos(); 307 EXPECT_TRUE(ver.VerifyConstantPoolContent()); 308 inner_literal_map.insert(ver.inner_literal_map_.begin(), ver.inner_literal_map_.end()); 309 } 310 std::ifstream base_file(base_file_name, std::ios::binary); 311 EXPECT_TRUE(base_file.is_open()); 312 313 std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); 314 315 ModifyBuffer(inner_literal_map, buffer); 316 317 const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_010.abc"; 318 GenerateModifiedAbc(buffer, target_file_name); 319 base_file.close(); 320 321 { 322 panda::verifier::Verifier ver {target_file_name}; 323 ver.CollectIdInfos(); 324 EXPECT_TRUE(ver.VerifyConstantPoolContent()); 325 } 326 } 327 328 /** 329 * @tc.name: verifier_constant_pool_011 330 * @tc.desc: Verify the method id in the literal array of the abc file. 331 * @tc.type: FUNC 332 * @tc.require: file path and name 333 */ 334 HWTEST_F(VerifierConstantPool, verifier_constant_pool_011, TestSize.Level1) 335 { 336 const std::string base_file_name = GRAPH_TEST_ABC_DIR "test_literal_array.abc"; 337 std::unordered_map<uint32_t, uint32_t> inner_method_map; 338 { 339 panda::verifier::Verifier ver {base_file_name}; 340 ver.CollectIdInfos(); 341 EXPECT_TRUE(ver.VerifyConstantPoolContent()); 342 inner_method_map.insert(ver.inner_method_map_.begin(), ver.inner_method_map_.end()); 343 } 344 std::ifstream base_file(base_file_name, std::ios::binary); 345 EXPECT_TRUE(base_file.is_open()); 346 347 std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(base_file), {}); 348 349 ModifyBuffer(inner_method_map, buffer); 350 351 const std::string target_file_name = GRAPH_TEST_ABC_DIR "verifier_constant_pool_011.abc"; 352 GenerateModifiedAbc(buffer, target_file_name); 353 base_file.close(); 354 355 { 356 panda::verifier::Verifier ver {target_file_name}; 357 ver.CollectIdInfos(); 358 EXPECT_FALSE(ver.VerifyConstantPoolContent()); 359 } 360 } 361 362 }; // namespace panda::verifier 363