1 /*
2 * Copyright (c) 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 "assembler/assembly-emitter.h"
17 #include "assembler/assembly-parser.h"
18 #include "libpandafile/class_data_accessor-inl.h"
19
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/jspandafile/js_pandafile.h"
22 #include "ecmascript/jspandafile/js_pandafile_executor.h"
23 #include "ecmascript/jspandafile/js_pandafile_manager.h"
24 #include "ecmascript/jspandafile/program_object.h"
25 #include "ecmascript/tests/test_helper.h"
26
27 using namespace panda::ecmascript;
28 using namespace panda::panda_file;
29 using namespace panda::pandasm;
30
31 namespace panda::test {
32 class JSPandaFileExecutorTest : public testing::Test {
33 public:
SetUpTestCase()34 static void SetUpTestCase()
35 {
36 GTEST_LOG_(INFO) << "SetUpTestCase";
37 }
38
TearDownTestCase()39 static void TearDownTestCase()
40 {
41 GTEST_LOG_(INFO) << "TearDownCase";
42 }
43
SetUp()44 void SetUp() override
45 {
46 TestHelper::CreateEcmaVMWithScope(instance, thread, scope, false, false, false);
47 }
48
TearDown()49 void TearDown() override
50 {
51 TestHelper::DestroyEcmaVMWithScope(instance, scope, false);
52 }
53
54 EcmaVM *instance {nullptr};
55 EcmaHandleScope *scope {nullptr};
56 JSThread *thread {nullptr};
57 };
58
HWTEST_F_L0(JSPandaFileExecutorTest,Execute)59 HWTEST_F_L0(JSPandaFileExecutorTest, Execute)
60 {
61 const char *fileName = "__JSPandaFileExecutorTest1.abc";
62 const char *data = R"(
63 .language ECMAScript
64 .function any func_main_0(any a0, any a1, any a2) {
65 ldai 1
66 return
67 }
68 )";
69 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
70 Parser parser;
71 auto res = parser.Parse(data);
72 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
73 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(fileName));
74 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
75 const File *file = pf->GetPandaFile();
76 File::EntityId classId = file->GetClassId(typeDesc);
77 ClassDataAccessor cda(*file, classId);
78 std::vector<File::EntityId> methodId {};
79 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
80 methodId.push_back(mda.GetMethodId());
81 });
82 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
83 MethodLiteral *method = new MethodLiteral(methodId[0]);
84 method->Initialize(pf.get());
85 pf->SetMethodLiteralToMap(method);
86 pfManager->AddJSPandaFile(pf);
87 Expected<JSTaggedValue, bool> result =
88 JSPandaFileExecutor::Execute(thread, pf.get(), JSPandaFile::ENTRY_MAIN_FUNCTION);
89 EXPECT_TRUE(result);
90 }
91
HWTEST_F_L0(JSPandaFileExecutorTest,ExecuteFromFile)92 HWTEST_F_L0(JSPandaFileExecutorTest, ExecuteFromFile)
93 {
94 const char *fileName = "__JSPandaFileExecutorTest2.abc";
95 const char *data = R"(
96 .language ECMAScript
97 .function any func_main_0(any a0, any a1, any a2) {
98 ldai 1
99 return
100 }
101 )";
102 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
103 Parser parser;
104 auto res = parser.Parse(data);
105 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
106 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(fileName));
107 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
108 const File *file = pf->GetPandaFile();
109 File::EntityId classId = file->GetClassId(typeDesc);
110 ClassDataAccessor cda(*file, classId);
111 std::vector<File::EntityId> methodId {};
112 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
113 methodId.push_back(mda.GetMethodId());
114 });
115 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
116 MethodLiteral *method = new MethodLiteral(methodId[0]);
117 method->Initialize(pf.get());
118 pf->SetMethodLiteralToMap(method);
119 pfManager->AddJSPandaFile(pf);
120 Expected<JSTaggedValue, bool> result =
121 JSPandaFileExecutor::ExecuteFromAbcFile(thread, CString(fileName), JSPandaFile::ENTRY_MAIN_FUNCTION);
122 EXPECT_TRUE(result);
123
124 pfManager->RemoveJSPandaFile(pf.get());
125 std::shared_ptr<JSPandaFile> foundPf = pfManager->FindJSPandaFile(fileName);
126 EXPECT_TRUE(foundPf == nullptr);
127
128 // readd panda file into mgr, due to panda file should managed by gc.
129 pfManager->AddJSPandaFile(pf);
130 }
131
HWTEST_F_L0(JSPandaFileExecutorTest,ExecuteFromBuffer)132 HWTEST_F_L0(JSPandaFileExecutorTest, ExecuteFromBuffer)
133 {
134 const char *fileName = "__JSPandaFileExecutorTest3.abc";
135 const char *data = R"(
136 .language ECMAScript
137 .function any func_main_0(any a0, any a1, any a2) {
138 ldai 1
139 return
140 }
141 )";
142 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
143 Parser parser;
144 auto res = parser.Parse(data);
145 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
146 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(fileName));
147 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
148 const File *file = pf->GetPandaFile();
149 File::EntityId classId = file->GetClassId(typeDesc);
150 ClassDataAccessor cda(*file, classId);
151 std::vector<File::EntityId> methodId {};
152 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
153 methodId.push_back(mda.GetMethodId());
154 });
155 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
156 MethodLiteral *method = new MethodLiteral(methodId[0]);
157 method->Initialize(pf.get());
158 pf->SetMethodLiteralToMap(method);
159 pfManager->AddJSPandaFile(pf);
160 Expected<JSTaggedValue, bool> result = JSPandaFileExecutor::ExecuteFromBuffer(
161 thread, (void *)data, sizeof(data), JSPandaFile::ENTRY_MAIN_FUNCTION, CString(fileName));
162 EXPECT_TRUE(result);
163
164 pfManager->RemoveJSPandaFile(pf.get());
165 std::shared_ptr<JSPandaFile> foundPf = pfManager->FindJSPandaFile(fileName);
166 EXPECT_TRUE(foundPf == nullptr);
167
168 // readd panda file into mgr, due to panda file should managed by gc.
169 pfManager->AddJSPandaFile(pf);
170 }
171
HWTEST_F_L0(JSPandaFileExecutorTest,ExecuteAbcFileWithSingletonPatternFlag)172 HWTEST_F_L0(JSPandaFileExecutorTest, ExecuteAbcFileWithSingletonPatternFlag)
173 {
174 int result = JSPandaFileExecutor::ExecuteAbcFileWithSingletonPatternFlag(thread, "",
175 "entry", JSPandaFile::ENTRY_MAIN_FUNCTION, false);
176 EXPECT_EQ(result, JSPandaFileExecutor::ROUTE_URI_ERROR);
177
178 int result1 = JSPandaFileExecutor::ExecuteAbcFileWithSingletonPatternFlag(thread, "com.application.example",
179 "entry", JSPandaFile::ENTRY_MAIN_FUNCTION, false);
180 EXPECT_EQ(result1, JSPandaFileExecutor::ROUTE_URI_ERROR);
181 }
182
HWTEST_F_L0(JSPandaFileExecutorTest,ExecuteInsecureAbcFile_1)183 HWTEST_F_L0(JSPandaFileExecutorTest, ExecuteInsecureAbcFile_1)
184 {
185 std::string fileName = QUICKFIX_ABC_PATH "multi_file/base/module.abc";
186 bool result = JSPandaFileExecutor::ExecuteInsecureAbcFile(thread, fileName.c_str());
187 EXPECT_TRUE(result == false);
188 }
189
HWTEST_F_L0(JSPandaFileExecutorTest,ExecuteInsecureAbcFile_2)190 HWTEST_F_L0(JSPandaFileExecutorTest, ExecuteInsecureAbcFile_2)
191 {
192 ecmascript::ThreadManagedScope managedScope(thread);
193 std::string fileName = QUICKFIX_ABC_PATH "multi_file/base/merge.abc";
194 bool result = JSPandaFileExecutor::ExecuteInsecureAbcFile(thread, fileName.c_str());
195 EXPECT_TRUE(result == true);
196 }
197 } // namespace panda::test
198