• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "file-inl.h"
17 #include "file_items.h"
18 #include "file_item_container.h"
19 #include "utils/string_helpers.h"
20 #include "zip_archive.h"
21 #include "file.h"
22 
23 #include "assembly-emitter.h"
24 #include "assembly-parser.h"
25 
26 #include <cstdint>
27 #ifdef PANDA_TARGET_MOBILE
28 #include <unistd.h>
29 #endif
30 
31 #include <vector>
32 
33 #include <gtest/gtest.h>
34 
35 namespace panda::panda_file::test {
36 
37 static constexpr const char *ABC_FILE = "test_file.abc";
38 
GetPandaFile(std::vector<uint8_t> * data)39 static std::unique_ptr<const File> GetPandaFile(std::vector<uint8_t> *data)
40 {
41     os::mem::ConstBytePtr ptr(reinterpret_cast<std::byte *>(data->data()), data->size(),
42                               [](std::byte *, size_t) noexcept {});
43     return File::OpenFromMemory(std::move(ptr));
44 }
45 
GetEmptyPandaFileBytes()46 static std::vector<uint8_t> GetEmptyPandaFileBytes()
47 {
48     pandasm::Parser p;
49 
50     auto source = R"()";
51 
52     std::string src_filename = "src.pa";
53     auto res = p.Parse(source, src_filename);
54     ASSERT(p.ShowError().err == pandasm::Error::ErrorType::ERR_NONE);
55 
56     auto pf = pandasm::AsmEmitter::Emit(res.Value());
57     ASSERT(pf != nullptr);
58 
59     std::vector<uint8_t> data {};
60     const auto header_ptr = reinterpret_cast<const uint8_t *>(pf->GetHeader());
61     data.assign(header_ptr, header_ptr + sizeof(File::Header));
62 
63     ASSERT(data.size() == sizeof(File::Header));
64 
65     return data;
66 }
67 
CreateOrAddZipPandaFile(std::vector<uint8_t> * data,const char * zip_archive_name,const char * filename,int append,int level)68 int CreateOrAddZipPandaFile(std::vector<uint8_t> *data, const char *zip_archive_name, const char *filename, int append,
69                             int level)
70 {
71     return CreateOrAddFileIntoZip(zip_archive_name, filename, (*data).data(), (*data).size(), append, level);
72 }
73 
CheckAnonMemoryName(const char * zip_archive_name)74 bool CheckAnonMemoryName([[maybe_unused]] const char *zip_archive_name)
75 {
76     // check if [annon:panda-classes.abc extracted in memory from /xx/__OpenPandaFileFromZip__.zip]
77 #ifdef PANDA_TARGET_MOBILE
78     bool result = false;
79     const char *prefix = "[anon:panda-";
80     int pid = getpid();
81     std::stringstream ss;
82     ss << "/proc/" << pid << "/maps";
83     std::ifstream f;
84     f.open(ss.str(), std::ios::in);
85     EXPECT_TRUE(f.is_open());
86     for (std::string line; std::getline(f, line);) {
87         if (line.find(prefix) != std::string::npos && line.find(zip_archive_name) != std::string::npos) {
88             result = true;
89         }
90     }
91     f.close();
92     return result;
93 #else
94     return true;
95 #endif
96 }
97 
98 HWTEST(File, GetClassByName, testing::ext::TestSize.Level0)
99 {
100     ItemContainer container;
101 
102     std::vector<std::string> names = {"C", "B", "A"};
103     std::vector<ClassItem *> classes;
104 
105     for (auto &name : names) {
106         classes.push_back(container.GetOrCreateClassItem(name));
107     }
108 
109     MemoryWriter mem_writer;
110 
111     ASSERT_TRUE(container.Write(&mem_writer));
112 
113     // Read panda file from memory
114 
115     auto data = mem_writer.GetData();
116     auto panda_file = GetPandaFile(&data);
117     ASSERT_NE(panda_file, nullptr);
118 
119     for (size_t i = 0; i < names.size(); i++) {
120         EXPECT_EQ(panda_file->GetClassId(reinterpret_cast<const uint8_t *>(names[i].c_str())).GetOffset(),
121                   classes[i]->GetOffset());
122     }
123 }
124 
125 HWTEST(File, OpenPandaFile, testing::ext::TestSize.Level0)
126 {
127     // Create ZIP
128     auto data = GetEmptyPandaFileBytes();
129     int ret;
130     const char *zip_filename = "__OpenPandaFile__.zip";
131     const char *filename1 = ARCHIVE_FILENAME;
132     const char *filename2 = "classses2.abc";  // just for testing.
133     ret = CreateOrAddZipPandaFile(&data, zip_filename, filename1, APPEND_STATUS_CREATE, Z_BEST_COMPRESSION);
134     ASSERT_EQ(ret, 0);
135     ret = CreateOrAddZipPandaFile(&data, zip_filename, filename2, APPEND_STATUS_ADDINZIP, Z_BEST_COMPRESSION);
136     ASSERT_EQ(ret, 0);
137 
138     // Open from ZIP
139     auto pf = OpenPandaFile(zip_filename);
140     EXPECT_NE(pf, nullptr);
141     EXPECT_STREQ((pf->GetFilename()).c_str(), zip_filename);
142 
143     // Open from ZIP with archive_filename
144     const char *filename3 = "classses3.abc";  // just for testing.
145     pf = OpenPandaFile(zip_filename, filename3);
146     EXPECT_NE(pf, nullptr);
147 
148     remove(zip_filename);
149 
150     ret = CreateOrAddZipPandaFile(&data, zip_filename, filename2, APPEND_STATUS_CREATE, Z_BEST_COMPRESSION);
151     ASSERT_EQ(ret, 0);
152 
153     // Open from ZIP without default archive_filename
154     pf = OpenPandaFile(zip_filename);
155     EXPECT_EQ(pf, nullptr);
156 
157     remove(zip_filename);
158 }
159 
160 HWTEST(File, OpenPandaFileFromMemory, testing::ext::TestSize.Level0)
161 {
162     auto pf = OpenPandaFileFromMemory(nullptr, -1);
163     EXPECT_EQ(pf, nullptr);
164 
165     pf = OpenPandaFileFromMemory(nullptr, 1U);
166     EXPECT_EQ(pf, nullptr);
167 
168     std::string tag = "ArkTS Code";
169     pf = OpenPandaFileFromMemory(nullptr, -1, tag);
170     EXPECT_EQ(pf, nullptr);
171 
172     tag = "";
173     pf = OpenPandaFileFromMemory(nullptr, 1U, tag);
174     EXPECT_EQ(pf, nullptr);
175 }
176 
177 HWTEST(File, OpenPandaFileFromSecureMemory, testing::ext::TestSize.Level0)
178 {
179     auto pf = OpenPandaFileFromSecureMemory(nullptr, -1);
180     EXPECT_EQ(pf, nullptr);
181 
182     pf = OpenPandaFileFromSecureMemory(nullptr, 1U);
183     EXPECT_EQ(pf, nullptr);
184 }
185 
186 HWTEST(File, OpenPandaFileFromZipNameAnonMem, testing::ext::TestSize.Level0)
187 {
188     // Create ZIP
189     auto data = GetEmptyPandaFileBytes();
190     int ret;
191     const char *zip_filename = "__OpenPandaFileFromZipNameAnonMem__.zip";
192     const char *filename1 = ARCHIVE_FILENAME;
193     ret = CreateOrAddZipPandaFile(&data, zip_filename, filename1, APPEND_STATUS_CREATE, Z_BEST_COMPRESSION);
194     ASSERT_EQ(ret, 0);
195 
196     // Open from ZIP
197     auto pf = OpenPandaFile(zip_filename);
198     EXPECT_NE(pf, nullptr);
199     EXPECT_STREQ((pf->GetFilename()).c_str(), zip_filename);
200     ASSERT_TRUE(CheckAnonMemoryName(zip_filename));
201 
202     remove(zip_filename);
203 }
204 
205 HWTEST(File, OpenPandaFileOrZip, testing::ext::TestSize.Level0)
206 {
207     // Create ZIP
208     auto data = GetEmptyPandaFileBytes();
209     int ret;
210     const char *zip_filename = "__OpenPandaFileOrZip__.zip";
211     const char *filename1 = ARCHIVE_FILENAME;
212     const char *filename2 = "classes2.abc";  // just for testing.
213     ret = CreateOrAddZipPandaFile(&data, zip_filename, filename1, APPEND_STATUS_CREATE, Z_BEST_COMPRESSION);
214     ASSERT_EQ(ret, 0);
215     ret = CreateOrAddZipPandaFile(&data, zip_filename, filename2, APPEND_STATUS_ADDINZIP, Z_BEST_COMPRESSION);
216     ASSERT_EQ(ret, 0);
217 
218     // Open from ZIP
219     auto pf = OpenPandaFileOrZip(zip_filename);
220     EXPECT_NE(pf, nullptr);
221     EXPECT_STREQ((pf->GetFilename()).c_str(), zip_filename);
222 
223     const char *zip_filename_with_entry = "__OpenPandaFileOrZip__.zip!/classes.abc";
224     auto pf_new = OpenPandaFileOrZip(zip_filename_with_entry);
225     EXPECT_NE(pf_new, nullptr);
226 
227     remove(zip_filename);
228 }
229 
230 HWTEST(File, OpenPandaFileFromZipErrorHandler, testing::ext::TestSize.Level0)
231 {
232     const char *file_name = "test_file_empty.panda";
233     {
234         auto writer = FileWriter(file_name);
235         ASSERT_TRUE(writer);
236     }
237     auto pf = OpenPandaFile(file_name);
238     EXPECT_EQ(pf, nullptr);
239 
240     const char *file_name_zip = "test_file_empty.zip";
241     {
242         auto writer = FileWriter(file_name);
243         ASSERT_TRUE(writer);
244         const std::vector<uint8_t> magic = {'P', 'K'};
245         ASSERT_TRUE(writer.WriteBytes(magic));
246     }
247     pf = OpenPandaFile(file_name_zip);
248     EXPECT_EQ(pf, nullptr);
249 
250     // Create ZIP
251     const char *file_name_zip_with_entry = "test_file_with_entry.zip";
252     std::vector<uint8_t> data = {};
253     int ret = CreateOrAddZipPandaFile(&data, file_name_zip_with_entry, ARCHIVE_FILENAME,
254         APPEND_STATUS_CREATE, Z_BEST_COMPRESSION);
255     ASSERT_EQ(ret, 0);
256     pf = OpenPandaFile(file_name_zip_with_entry);
257     EXPECT_EQ(pf, nullptr);
258 
259     auto fp = fopen(file_name_zip_with_entry, "a");
260     EXPECT_NE(fp, nullptr);
261     const char append_str[] = "error";
262     EXPECT_EQ(fwrite(append_str, sizeof(append_str), 1U, fp), 1U);
263     fclose(fp);
264     pf = OpenPandaFile(file_name_zip_with_entry);
265     EXPECT_EQ(pf, nullptr);
266 
267     remove(file_name);
268     remove(file_name_zip);
269     remove(file_name_zip_with_entry);
270 }
271 
272 HWTEST(File, HandleArchive, testing::ext::TestSize.Level0)
273 {
274     {
275         ItemContainer container;
276         auto writer = FileWriter(ARCHIVE_FILENAME);
277         ASSERT_TRUE(container.Write(&writer));
278         ASSERT_TRUE(writer.Align(4U));  // to 4 bytes align
279     }
280 
281     std::vector<uint8_t> data;
282     {
283         std::ifstream in(ARCHIVE_FILENAME, std::ios::binary);
284         data.insert(data.end(), (std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
285         ASSERT_TRUE(data.size() > 0U && data.size() % 4U == 0U);
286     }
287 
288     // Create ZIP
289     const char *zip_filename = "__HandleArchive__.zip";
290     int ret = CreateOrAddZipPandaFile(&data, zip_filename, ARCHIVE_FILENAME, APPEND_STATUS_CREATE, Z_NO_COMPRESSION);
291     ASSERT_EQ(ret, 0);
292     auto pf = OpenPandaFile(zip_filename);
293     EXPECT_NE(pf, nullptr);
294 
295     remove(ARCHIVE_FILENAME);
296     remove(zip_filename);
297 }
298 
299 HWTEST(File, CheckHeader, testing::ext::TestSize.Level0)
300 {
301     // Write panda file to disk
302     ItemContainer container;
303 
304     auto writer = FileWriter(ABC_FILE);
305     ASSERT_TRUE(container.Write(&writer));
306 
307     // Read panda file from disk
308     auto fp = fopen(ABC_FILE, "rb");
309     EXPECT_NE(fp, nullptr);
310 
311     os::mem::ConstBytePtr ptr = os::mem::MapFile(os::file::File(fileno(fp)), os::mem::MMAP_PROT_READ,
312         os::mem::MMAP_FLAG_PRIVATE, writer.GetOffset()).ToConst();
313     EXPECT_NE(ptr.Get(), nullptr);
314     EXPECT_TRUE(CheckHeader(ptr, ABC_FILE));
315     fclose(fp);
316 
317     remove(ABC_FILE);
318 }
319 
320 HWTEST(File, GetFileType, testing::ext::TestSize.Level0)
321 {
322     // Write panda file to disk
323     ItemContainer container;
324 
325     auto writer = FileWriter(ABC_FILE);
326     ASSERT_TRUE(container.Write(&writer));
327 
328     os::file::File file = os::file::Open(ABC_FILE, os::file::Mode::READONLY);
329     ASSERT_TRUE(file.IsValid());
330     os::file::FileHolder fhHolder(file);
331     auto res = file.GetFileSize();
332     size_t size = res.Value();
333     os::mem::ConstBytePtr ptr =
334         os::mem::MapFile(file, os::mem::MMAP_PROT_READ, os::mem::MMAP_FLAG_PRIVATE, size).ToConst();
335     const uint8_t *data = reinterpret_cast<const uint8_t *>(ptr.Get());
336     panda::panda_file::PandaFileType fileType = panda::panda_file::GetFileType(data, static_cast<int32_t>(size));
337     EXPECT_EQ(fileType, panda::panda_file::PandaFileType::FILE_DYNAMIC);
338     remove(ABC_FILE);
339 }
340 
341 HWTEST(File, GetMode, testing::ext::TestSize.Level0)
342 {
343     // Write panda file to disk
344     ItemContainer container;
345 
346     auto writer = FileWriter(ABC_FILE);
347     ASSERT_TRUE(container.Write(&writer));
348 
349     // Read panda file from disk
350     EXPECT_NE(File::Open(ABC_FILE), nullptr);
351     EXPECT_EQ(File::Open(ABC_FILE, File::OpenMode::WRITE_ONLY), nullptr);
352 
353     remove(ABC_FILE);
354 }
355 
356 HWTEST(File, Open, testing::ext::TestSize.Level0)
357 {
358     EXPECT_EQ(File::Open(ABC_FILE), nullptr);
359 
360     auto fp = fopen(ABC_FILE, "w");
361     EXPECT_NE(fp, nullptr);
362     const char write_str[] = "error";
363     EXPECT_EQ(fwrite(write_str, sizeof(write_str), 1U, fp), 1U);
364     fclose(fp);
365     EXPECT_EQ(File::Open(ABC_FILE), nullptr);
366     EXPECT_EQ(File::Open(ABC_FILE, File::OpenMode::WRITE_ONLY), nullptr);
367 
368     remove(ABC_FILE);
369 }
370 
371 HWTEST(File, OpenUncompressedArchive, testing::ext::TestSize.Level0)
372 {
373     // Invalid FD
374     EXPECT_EQ(File::OpenUncompressedArchive(-1, ABC_FILE, 0U, 0U), nullptr);
375 
376     // Invalid Size
377     EXPECT_EQ(File::OpenUncompressedArchive(1, ABC_FILE, 0U, 0U), nullptr);
378 
379     // Invalid Max Size
380     EXPECT_EQ(File::OpenUncompressedArchive(1, ABC_FILE, -1, 0U), nullptr);
381 
382     // Invalid ABC File
383     auto data = GetEmptyPandaFileBytes();
384     auto fp = fopen(ARCHIVE_FILENAME, "w+");
385     EXPECT_NE(fp, nullptr);
386     data[0] = 0U;
387     EXPECT_EQ(fwrite(data.data(), sizeof(uint8_t), data.size(), fp), data.size());
388     (void)fseek(fp, 0, SEEK_SET);
389     EXPECT_EQ(File::OpenUncompressedArchive(fileno(fp), ARCHIVE_FILENAME, sizeof(File::Header), 0U), nullptr);
390     fclose(fp);
391 
392     remove(ABC_FILE);
393 }
394 
395 HWTEST(File, CheckSecureMem, testing::ext::TestSize.Level0)
396 {
397     uint8_t *data1 = nullptr;
398     uintptr_t value1 = reinterpret_cast<uintptr_t>(data1);
399     bool res1 = CheckSecureMem(value1, 0); // 0: size
400     EXPECT_TRUE(res1);
401 
402     int data2 = 256;
403     uintptr_t value2 = reinterpret_cast<uintptr_t>(&data2);
404     bool res2 = CheckSecureMem(value2, 1000);
405     EXPECT_TRUE(res2);
406 
407     int data3 = 41235235;
408     uintptr_t value3 = reinterpret_cast<uintptr_t>(&data3);
409     bool res3 = CheckSecureMem(value3, static_cast<size_t>(243423423523));
410     EXPECT_TRUE(res3);
411 }
412 
413 HWTEST(File, CheckLiteralArray, testing::ext::TestSize.Level0)
414 {
415     // Write panda file to disk
416     ItemContainer container;
417 
418     auto writer = FileWriter(ABC_FILE);
419     ASSERT_TRUE(container.Write(&writer));
420 
421     // Read panda file from disk
422     auto fp = fopen(ABC_FILE, "rb");
423     EXPECT_NE(fp, nullptr);
424 
425     os::mem::ConstBytePtr ptr =
426         os::mem::MapFile(os::file::File(fileno(fp)), os::mem::MMAP_PROT_READ | os::mem::MMAP_PROT_WRITE,
427                          os::mem::MMAP_FLAG_PRIVATE, writer.GetOffset())
428             .ToConst();
429     EXPECT_NE(ptr.Get(), nullptr);
430     EXPECT_TRUE(CheckHeader(ptr, ABC_FILE));
431 
432     auto header = reinterpret_cast<File::Header *>(reinterpret_cast<uintptr_t>(ptr.Get()));
433     auto num_literalarrays = header->num_literalarrays;
434     uint32_t i = 10;
435     header->num_literalarrays = i;
436     EXPECT_FALSE(CheckHeader(ptr, ABC_FILE));
437     header->num_literalarrays = num_literalarrays;
438     header->literalarray_idx_off = i;
439     EXPECT_FALSE(CheckHeader(ptr, ABC_FILE));
440     fclose(fp);
441 
442     remove(ABC_FILE);
443 }
444 
445 }  // namespace panda::panda_file::test
446