• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "native_module_manager.h"
17 
18 #include <cstring>
19 #include <dirent.h>
20 #include <fstream>
21 #include <iostream>
22 #include <mutex>
23 #include <sstream>
24 #include <unistd.h>
25 
26 #ifdef ENABLE_HITRACE
27 #include "hitrace_meter.h"
28 #endif
29 #include "module_load_checker.h"
30 #include "native_engine/native_engine.h"
31 #include "securec.h"
32 #include "utils/log.h"
33 
34 #define NDK "ndk"
35 #define ALLOW_ALL_SHARED_LIBS "allow_all_shared_libs"
36 
37 namespace {
38 constexpr static int32_t MODULE_PATH_SECONDARY_INDEX = 2;
39 constexpr static int32_t NATIVE_PATH_NUMBER = 3;
40 constexpr static int32_t IS_APP_MODULE_FLAGS = 100;
41 thread_local bool g_isLoadingModule = false;
42 enum ModuleLoadFailedReason : uint32_t {
43     MODULE_LOAD_SUCCESS = 0,
44     MODULE_NOT_EXIST    = 1,
45 };
46 } // namespace
47 
48 NativeModuleManager* NativeModuleManager::instance_ = NULL;
49 std::mutex g_instanceMutex;
50 
NativeModuleManager()51 NativeModuleManager::NativeModuleManager()
52 {
53     HILOG_DEBUG("enter");
54     pthread_mutex_init(&mutex_, nullptr);
55     moduleLoadChecker_ = std::make_unique<ModuleLoadChecker>();
56 }
57 
~NativeModuleManager()58 NativeModuleManager::~NativeModuleManager()
59 {
60     HILOG_INFO("enter");
61     {
62         std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
63         NativeModule* nativeModule = headNativeModule_;
64         while (nativeModule != nullptr) {
65             nativeModule = nativeModule->next;
66             if (headNativeModule_->name) {
67                 delete[] headNativeModule_->name;
68             }
69             if (headNativeModule_->moduleName) {
70                 delete[] headNativeModule_->moduleName;
71             }
72             if (headNativeModule_->jsABCCode) {
73                 delete[] headNativeModule_->jsABCCode;
74             }
75             delete headNativeModule_;
76             headNativeModule_ = nativeModule;
77         }
78         headNativeModule_ = nullptr;
79         tailNativeModule_ = nullptr;
80     }
81 
82 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
83     !defined(LINUX_PLATFORM)
84     if (sharedLibsSonames_) {
85         delete[] sharedLibsSonames_;
86     }
87 #endif
88     appLibPathMapMutex_.lock();
89     for (const auto& item : appLibPathMap_) {
90         delete[] item.second;
91     }
92     std::map<std::string, char*>().swap(appLibPathMap_);
93     appLibPathMapMutex_.unlock();
94 
95     while (nativeEngineList_.size() > 0) {
96         NativeEngine* wraper = nativeEngineList_.begin()->second;
97         if (wraper != nullptr) {
98             delete wraper;
99             wraper = nullptr;
100         }
101         nativeEngineList_.erase(nativeEngineList_.begin());
102     }
103     pthread_mutex_destroy(&mutex_);
104 }
105 
GetInstance()106 NativeModuleManager* NativeModuleManager::GetInstance()
107 {
108     if (instance_ == NULL) {
109         std::lock_guard<std::mutex> lock(g_instanceMutex);
110         if (instance_ == NULL) {
111             instance_ = new NativeModuleManager();
112             HILOG_DEBUG("create native module manager instance");
113         }
114     }
115     return instance_;
116 }
117 
SetNativeEngine(std::string moduleKey,NativeEngine * nativeEngine)118 void NativeModuleManager::SetNativeEngine(std::string moduleKey, NativeEngine* nativeEngine)
119 {
120     HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
121     if (nativeEngine != nullptr) {
122         nativeEngine->SetModuleName(moduleKey);
123     }
124     std::lock_guard<std::mutex> lock(nativeEngineListMutex_);
125     nativeEngineList_.emplace(moduleKey, nativeEngine);
126 }
127 
EmplaceModuleLib(std::string moduleKey,const LIBHANDLE lib)128 void NativeModuleManager::EmplaceModuleLib(std::string moduleKey, const LIBHANDLE lib)
129 {
130     HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
131     std::lock_guard<std::mutex> lock(moduleLibMutex_);
132     if (lib != nullptr) {
133         moduleLibMap_.emplace(moduleKey, lib);
134     }
135 }
136 
RemoveModuleLib(const std::string moduleKey)137 bool NativeModuleManager::RemoveModuleLib(const std::string moduleKey)
138 {
139     HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
140     bool deleted = false;
141     std::lock_guard<std::mutex> lock(moduleLibMutex_);
142     auto it = moduleLibMap_.find(moduleKey);
143     if (it != moduleLibMap_.end()) {
144         moduleLibMap_.erase(it);
145         HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
146         deleted = true;
147     }
148     return deleted;
149 }
150 
GetNativeModuleHandle(const std::string & moduleKey) const151 LIBHANDLE NativeModuleManager::GetNativeModuleHandle(const std::string& moduleKey) const
152 {
153     HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
154     std::lock_guard<std::mutex> lock(moduleLibMutex_);
155     auto it = moduleLibMap_.find(moduleKey);
156     if (it == moduleLibMap_.end()) {
157         return nullptr;
158     }
159     return it->second;
160 }
161 
EmplaceModuleBuffer(const std::string moduleKey,const uint8_t * lib)162 void NativeModuleManager::EmplaceModuleBuffer(const std::string moduleKey, const uint8_t* lib)
163 {
164     HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
165     std::lock_guard<std::mutex> lock(moduleBufMutex_);
166     if (lib != nullptr) {
167         moduleBufMap_.emplace(moduleKey, lib);
168     }
169 }
170 
RemoveModuleBuffer(const std::string moduleKey)171 bool NativeModuleManager::RemoveModuleBuffer(const std::string moduleKey)
172 {
173     HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
174     bool deleted = false;
175     std::lock_guard<std::mutex> lock(moduleBufMutex_);
176     auto it = moduleBufMap_.find(moduleKey);
177     if (it != moduleBufMap_.end()) {
178         moduleBufMap_.erase(it);
179         HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
180         deleted = true;
181     }
182     return deleted;
183 }
184 
GetBufferHandle(const std::string & moduleKey) const185 const uint8_t* NativeModuleManager::GetBufferHandle(const std::string& moduleKey) const
186 {
187     HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
188     std::lock_guard<std::mutex> lock(moduleBufMutex_);
189     auto it = moduleBufMap_.find(moduleKey);
190     if (it == moduleBufMap_.end()) {
191         return nullptr;
192     }
193     return it->second;
194 }
195 
RemoveNativeModule(const std::string & moduleKey)196 bool NativeModuleManager::RemoveNativeModule(const std::string& moduleKey)
197 {
198     bool handleAbcRemoved = RemoveModuleBuffer(moduleKey);
199     bool handleRemoved = RemoveModuleLib(moduleKey);
200     bool moduleRemoved = RemoveNativeModuleByCache(moduleKey);
201 
202     HILOG_DEBUG("handleAbcRemoved is %{public}d, handleRemoved is %{public}d, moduleRemoved is %{public}d",
203         handleAbcRemoved, handleRemoved, moduleRemoved);
204     return ((handleRemoved || handleAbcRemoved) && moduleRemoved);
205 }
206 
UnloadNativeModule(const std::string & moduleKey)207 bool NativeModuleManager::UnloadNativeModule(const std::string& moduleKey)
208 {
209     HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
210     LIBHANDLE handle = GetNativeModuleHandle(moduleKey);
211     if (handle == nullptr) {
212         HILOG_ERROR("failed to get native module handle.");
213         return false;
214     }
215 
216     if (RemoveNativeModule(moduleKey) == false) {
217         HILOG_ERROR("remove native module failed.");
218         return false;
219     }
220 
221     return UnloadModuleLibrary(handle);
222 }
223 
GetModuleFileName(const char * moduleName,bool isAppModule)224 std::string NativeModuleManager::GetModuleFileName(const char* moduleName, bool isAppModule)
225 {
226     if (moduleName == nullptr) {
227         HILOG_ERROR("invalid param. moduleName is nullptr");
228         return "";
229     }
230     HILOG_INFO("moduleName is '%{public}s', isAppModule is %{public}d", moduleName, isAppModule);
231 
232     std::string loadPath;
233     std::string name = isAppModule ? (prefix_ + "/" + moduleName) : moduleName;
234     char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
235     const char* pathKey = "default";
236     if (!GetNativeModulePath(moduleName, pathKey, "", isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
237         HILOG_ERROR("get native module path failed");
238         return loadPath;
239     }
240     NativeModule* cacheNativeModule = nullptr;
241     NativeModuleHeadTailStruct cacheHeadTailNativeModule;
242     NativeModule* module =
243         FindNativeModuleByCache(name.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
244     if (module == nullptr) {
245         HILOG_ERROR("get module file name failed");
246         return loadPath;
247     }
248     loadPath = nativeModulePath[0];
249     if (isAppModule && IsExistedPath(pathKey)) {
250         std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
251         loadPath = std::string(appLibPathMap_[pathKey]) + "/" + nativeModulePath[0];
252     }
253     HILOG_ERROR("get module file name failed, moduleName is %{public}s", moduleName);
254     return loadPath;
255 }
256 
Register(NativeModule * nativeModule)257 void NativeModuleManager::Register(NativeModule* nativeModule)
258 {
259     if (nativeModule == nullptr) {
260         HILOG_ERROR("nativeModule value is null");
261         return;
262     }
263 
264     HILOG_DEBUG("native module name is '%{public}s'", nativeModule->name);
265     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
266     const char *nativeModuleName = nativeModule->name == nullptr ? "" : nativeModule->name;
267     std::string appName = prefix_ + "/" + nativeModuleName;
268     std::string tmpName = isAppModule_ ? appName : nativeModuleName;
269     if (nativeModule->flags == IS_APP_MODULE_FLAGS) {
270         std::string prefix = "default/";
271         tmpName = prefix + nativeModuleName;
272     }
273     char *moduleName = strdup(tmpName.c_str());
274     if (moduleName == nullptr) {
275         HILOG_ERROR("strdup failed. tmpName is %{public}s", tmpName.c_str());
276         return;
277     }
278 
279     if (g_isLoadingModule || !strcmp(loadingModuleName_.c_str(), moduleName)) {
280         if (!CreateTailNativeModule()) {
281             HILOG_ERROR("create tail nativeModule failed");
282             free(moduleName);
283             return;
284         }
285         tailNativeModule_->version = nativeModule->version;
286         tailNativeModule_->fileName = nativeModule->fileName;
287         tailNativeModule_->isAppModule = isAppModule_;
288         tailNativeModule_->name = moduleName;
289         tailNativeModule_->moduleName = nullptr;  /* we update moduleName latter */
290         tailNativeModule_->refCount = nativeModule->refCount;
291         tailNativeModule_->registerCallback = nativeModule->registerCallback;
292         tailNativeModule_->getJSCode = nativeModule->getJSCode;
293         tailNativeModule_->getABCCode = nativeModule->getABCCode;
294         tailNativeModule_->next = nullptr;
295         tailNativeModule_->moduleLoaded = true;
296         tailNativeModule_->systemFilePath = "";
297         if (isAppModule_) {
298             HILOG_INFO("At tail register module name is '%{public}s'", tailNativeModule_->name);
299         }
300         HILOG_DEBUG("At tail register module name is '%{public}s', isAppModule is %{public}d", tailNativeModule_->name,
301             isAppModule_);
302     } else {
303         if (!CreateHeadNativeModule()) {
304             HILOG_ERROR("create head nativeModule failed");
305             return;
306         }
307         headNativeModule_->version = nativeModule->version;
308         headNativeModule_->fileName = nativeModule->fileName;
309         headNativeModule_->isAppModule = isAppModule_;
310         headNativeModule_->name = moduleName;
311         headNativeModule_->refCount = nativeModule->refCount;
312         headNativeModule_->registerCallback = nativeModule->registerCallback;
313         headNativeModule_->getJSCode = nativeModule->getJSCode;
314         headNativeModule_->getABCCode = nativeModule->getABCCode;
315         headNativeModule_->moduleLoaded = true;
316         headNativeModule_->systemFilePath = "";
317         HILOG_INFO("At head register module name is '%{public}s', isAppModule is %{public}d",
318             headNativeModule_->name, isAppModule_);
319     }
320 }
321 
CreateHeadNativeModule()322 bool NativeModuleManager::CreateHeadNativeModule()
323 {
324     if (headNativeModule_ == tailNativeModule_ && tailNativeModule_ == nullptr) {
325         headNativeModule_ = new NativeModule();
326         if (headNativeModule_ == nullptr) {
327             HILOG_ERROR("first NativeModule create failed");
328             return false;
329         }
330         tailNativeModule_ = headNativeModule_;
331     } else {
332         auto head = new NativeModule();
333         if (head == nullptr) {
334             HILOG_ERROR("head NativeModule create failed");
335             return false;
336         }
337         if (headNativeModule_) {
338             head->next = headNativeModule_;
339             headNativeModule_ = head;
340         }
341     }
342     return true;
343 }
344 
CreateTailNativeModule()345 bool NativeModuleManager::CreateTailNativeModule()
346 {
347     if (headNativeModule_ == tailNativeModule_ && tailNativeModule_ == nullptr) {
348         headNativeModule_ = new NativeModule();
349         if (headNativeModule_ == nullptr) {
350             HILOG_ERROR("first NativeModule create failed");
351             return false;
352         }
353         tailNativeModule_ = headNativeModule_;
354     } else {
355         auto tail = new NativeModule();
356         if (tail == nullptr) {
357             HILOG_ERROR("tail NativeModule create failed");
358             return false;
359         }
360         if (tailNativeModule_) {
361             tailNativeModule_->next = tail;
362             tailNativeModule_ = tailNativeModule_->next;
363         }
364     }
365     return true;
366 }
367 
368 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
369     !defined(LINUX_PLATFORM)
CreateSharedLibsSonames()370 void NativeModuleManager::CreateSharedLibsSonames()
371 {
372     HILOG_DEBUG("enter");
373     const char* allowList[] = {
374         // bionic library
375         "libc.so",
376         "libdl.so",
377         "libm.so",
378         "libz.so",
379         "libclang_rt.asan.so",
380         "libclang_rt.tsan.so",
381         "libclang_rt.ubsan_standalone.so",
382         "libclang_rt.ubsan_minimal.so",
383         "libclang_rt.hwasan.so",
384         // z library
385         "libace_napi.z.so",
386         "libace_ndk.z.so",
387         "libcj_environment.z.so",
388         "libbundle_ndk.z.so",
389         "libdeviceinfo_ndk.z.so",
390         "libEGL.so",
391         "libGLESv3.so",
392         "libhiappevent_ndk.z.so",
393         "libhuks_ndk.z.so",
394         "libhukssdk.z.so",
395         "libnative_drawing.so",
396         "libnative_window.so",
397         "libnative_buffer.so",
398         "libnative_vsync.so",
399         "libOpenSLES.so",
400         "libpixelmap_ndk.z.so",
401         "libimage_ndk.z.so",
402         "libimage_receiver_ndk.z.so",
403         "libimage_source_ndk.z.so",
404         "librawfile.z.so",
405         "libuv.so",
406         "libhilog.so",
407         "libnative_image.so",
408         "libnative_media_adec.so",
409         "libnative_media_aenc.so",
410         "libnative_media_codecbase.so",
411         "libnative_media_core.so",
412         "libnative_media_vdec.so",
413         "libnative_media_venc.so",
414         "libnative_media_avmuxer.so",
415         "libnative_media_avdemuxer.so",
416         "libnative_media_avsource.so",
417         "libnative_avscreen_capture.so",
418         "libavplayer.so",
419         "libavrecorder.so",
420         // adaptor library
421         "libohosadaptor.so",
422         "libusb_ndk.z.so",
423         "libvulkan.so",
424     };
425 
426     size_t allowListLength = sizeof(allowList) / sizeof(char*);
427     int32_t sharedLibsSonamesLength = 1;
428     for (size_t i = 0; i < allowListLength; i++) {
429         sharedLibsSonamesLength += strlen(allowList[i]) + 1;
430     }
431     sharedLibsSonames_ = new char[sharedLibsSonamesLength];
432     int32_t cursor = 0;
433     for (size_t i = 0; i < allowListLength; i++) {
434         if (sprintf_s(sharedLibsSonames_ + cursor, sharedLibsSonamesLength - cursor, "%s:", allowList[i]) == -1) {
435             delete[] sharedLibsSonames_;
436             sharedLibsSonames_ = nullptr;
437             return;
438         }
439         cursor += strlen(allowList[i]) + 1;
440     }
441     sharedLibsSonames_[cursor] = '\0';
442 }
443 #endif
444 
CreateLdNamespace(const std::string moduleName,const char * lib_ld_path,const bool & isSystemApp)445 void NativeModuleManager::CreateLdNamespace(const std::string moduleName, const char* lib_ld_path,
446                                             [[maybe_unused]] const bool& isSystemApp)
447 {
448 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
449     !defined(LINUX_PLATFORM)
450     Dl_namespace current_ns;
451     Dl_namespace ns;
452 
453     // Create module ns.
454     std::string nsName = "moduleNs_" + moduleName;
455     dlns_init(&ns, nsName.c_str());
456     dlns_get(nullptr, &current_ns);
457 
458     Dl_namespace ndk_ns;
459     dlns_get(NDK, &ndk_ns);
460 
461     if (isSystemApp) {
462         /*
463          * The app's so may have the same name as the system library, LOCAL_NS_PREFERED means linker will check
464          * and use the app's so first.
465          */
466         dlns_create2(&ns, lib_ld_path, LOCAL_NS_PREFERED);
467         // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
468         dlns_set_namespace_separated(nsName.c_str(), true);
469         // Allows access to subdirectories of this directory for shared objects (so).
470         dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
471         // System app can visit all ndk and default ns libs.
472         if (strlen(ndk_ns.name) > 0) {
473             dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
474             dlns_inherit(&ndk_ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
475             dlns_inherit(&current_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
476             dlns_inherit(&ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
477         }
478     } else {
479         dlns_create2(&ns, lib_ld_path, 0);
480         // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
481         dlns_set_namespace_separated(nsName.c_str(), true);
482         // Allows access to subdirectories of this directory for shared objects (so).
483         dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
484         // Non-system app can visit all ndk ns libs and default ns shared libs.
485         if (!sharedLibsSonames_) {
486             CreateSharedLibsSonames();
487         }
488         dlns_inherit(&ns, &current_ns, sharedLibsSonames_);
489         if (strlen(ndk_ns.name) > 0) {
490             dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
491             dlns_inherit(&ndk_ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
492             dlns_inherit(&current_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
493         }
494     }
495 
496     nsMap_[moduleName] = ns;
497 
498     HILOG_DEBUG("end. moduleName: %{public}s, path: %{public}s", moduleName.c_str(), lib_ld_path);
499 #endif
500 }
501 
SetAppLibPath(const std::string & moduleName,const std::vector<std::string> & appLibPath,const bool & isSystemApp)502 void NativeModuleManager::SetAppLibPath(const std::string& moduleName, const std::vector<std::string>& appLibPath,
503                                         const bool& isSystemApp)
504 {
505     HILOG_DEBUG("moduleName is %{public}s, isisSystemApp is %{public}d", moduleName.c_str(), isSystemApp);
506 
507     std::string tmpPath = "";
508     for (size_t i = 0; i < appLibPath.size(); i++) {
509         if (appLibPath[i].empty()) {
510             continue;
511         }
512         tmpPath += appLibPath[i];
513         tmpPath += ":";
514     }
515     if (tmpPath.back() == ':') {
516         tmpPath.pop_back();
517     }
518 
519     char *tmp = strdup(tmpPath.c_str());
520     if (tmp == nullptr) {
521         HILOG_ERROR("strdup failed. tmpPath is %{public}s", tmpPath.c_str());
522         return;
523     }
524 
525     std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
526     if (appLibPathMap_[moduleName] != nullptr) {
527         delete[] appLibPathMap_[moduleName];
528     }
529     appLibPathMap_[moduleName] = tmp;
530     CreateLdNamespace(moduleName, tmp, isSystemApp);
531     HILOG_DEBUG("path: %{public}s", appLibPathMap_[moduleName]);
532 }
533 
MoveApiAllowListCheckerPtr(std::unique_ptr<ApiAllowListChecker> & apiAllowListChecker,NativeModule * nativeModule)534 void NativeModuleManager::MoveApiAllowListCheckerPtr(
535     std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, NativeModule* nativeModule)
536 {
537     if (apiAllowListChecker != nullptr) {
538         nativeModule->apiAllowListChecker.reset(apiAllowListChecker.release());
539     }
540 }
541 
LoadNativeModule(const char * moduleName,const char * path,bool isAppModule,std::string & errInfo,bool internal,const char * relativePath)542 NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, const char* path, bool isAppModule,
543     std::string& errInfo, bool internal, const char* relativePath)
544 {
545     if (moduleName == nullptr) {
546         errInfo = "load native module failed. moduleName is nullptr";
547         HILOG_ERROR("%{public}s", errInfo.c_str());
548         return nullptr;
549     }
550 
551     if (relativePath == nullptr) {
552         errInfo = "load native module failed. relativePath is nullptr";
553         HILOG_ERROR("%{public}s", errInfo.c_str());
554         return nullptr;
555     }
556 
557     std::string relativePathStr(relativePath);
558     if (relativePathStr.find("..") != std::string::npos) {
559         HILOG_ERROR("get relativePath error,relativePath contains .., moduleName:%{public}s", moduleName);
560         return nullptr;
561     }
562 
563     HILOG_DEBUG("moduleName is %{public}s, path is %{public}s, relativePath is %{public}s",
564         moduleName, path, relativePath);
565 
566     std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
567     if (moduleLoadChecker_ && !moduleLoadChecker_->DiskCheckOnly() &&
568         !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker, isAppModule)) {
569         errInfo = "module " + std::string(moduleName) + " is in blocklist, loading prohibited";
570         HILOG_ERROR("%{public}s", errInfo.c_str());
571         return nullptr;
572     }
573     std::string prefixTmp;
574 #if defined(ANDROID_PLATFORM)
575     std::string strModule(moduleName);
576     std::string strCutName = strModule;
577     if (path != nullptr) {
578         if (IsExistedPath(path)) {
579             strModule = path;
580         }
581         prefixTmp = "default";
582         strModule = prefixTmp + '/' + moduleName;
583     } else {
584         path = "default";
585         if (strModule.find(".") != std::string::npos) {
586             char* temp = const_cast<char*>(strCutName.c_str());
587             for (char* p = strchr(temp, '.'); p != nullptr; p = strchr(p + 1, '.')) {
588                 *p = '_';
589             }
590         }
591     }
592 #endif
593 
594     char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
595     nativeModulePath[0][0] = 0;
596     nativeModulePath[1][0] = 0;
597     nativeModulePath[2][0] = 0; // 2 : Element index value
598     NativeModule* cacheNativeModule = nullptr;
599     NativeModuleHeadTailStruct cacheHeadTailNativeModule;
600 #if defined(ANDROID_PLATFORM)
601     if (!GetNativeModulePath(strCutName.c_str(), path, relativePath, isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
602         errInfo = "failed to get native file path of module " + std::string(moduleName);
603         HILOG_WARN("%{public}s", errInfo.c_str());
604         return nullptr;
605     }
606     NativeModule* nativeModule =
607         FindNativeModuleByCache(strModule.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
608 #else
609     std::string key(moduleName);
610     if (isAppModule) {
611         prefixTmp = "default";
612         if (path && IsExistedPath(path)) {
613             prefixTmp = path;
614         }
615         key = prefixTmp + '/' + moduleName;
616         HILOG_INFO("key is %{public}s", key.c_str());
617     }
618     if (!GetNativeModulePath(moduleName, prefixTmp.c_str(), relativePath, isAppModule, nativeModulePath,
619                              NAPI_PATH_MAX)) {
620         errInfo = "failed to get native file path of module " + std::string(moduleName);
621         HILOG_WARN("%{public}s", errInfo.c_str());
622         return nullptr;
623     }
624 #ifdef ENABLE_HITRACE
625     StartTrace(HITRACE_TAG_ACE, moduleName);
626 #endif
627     NativeModule* nativeModule =
628         FindNativeModuleByCache(key.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
629 #endif
630     if (nativeModule == nullptr) {
631         (void)pthread_mutex_lock(&mutex_);
632 #ifndef IOS_PLATFORM
633         if (CheckNativeListChanged(cacheHeadTailNativeModule.headNativeModule,
634                                    cacheHeadTailNativeModule.tailNativeModule)) {
635 #ifdef ANDROID_PLATFORM
636             nativeModule = FindNativeModuleByCache(strModule.c_str(), nativeModulePath, cacheNativeModule,
637                                                    cacheHeadTailNativeModule);
638 #else
639             nativeModule =
640                 FindNativeModuleByCache(key.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
641 #endif
642         }
643 #else
644 #endif
645         if (nativeModule == nullptr) {
646             prefix_ = prefixTmp;
647             isAppModule_ = isAppModule;
648             g_isLoadingModule = true;
649 #ifdef ANDROID_PLATFORM
650             HILOG_DEBUG("module '%{public}s' does not in cache", strCutName.c_str());
651             nativeModule = FindNativeModuleByDisk(strCutName.c_str(), path, relativePath, internal, isAppModule,
652                                                   errInfo, nativeModulePath, cacheNativeModule);
653 #elif defined(IOS_PLATFORM)
654             nativeModule =
655                 FindNativeModuleByCache(moduleName, nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
656             if (nativeModule == nullptr) {
657                 HILOG_DEBUG("module '%{public}s' does not in cache", moduleName);
658                 nativeModule = FindNativeModuleByDisk(moduleName, path, relativePath, internal, isAppModule, errInfo,
659                                                       nativeModulePath, cacheNativeModule);
660             }
661 #else
662             HILOG_DEBUG("module '%{public}s' does not in cache", moduleName);
663             nativeModule = FindNativeModuleByDisk(moduleName, prefix_.c_str(), relativePath, internal, isAppModule,
664                                                   errInfo, nativeModulePath, cacheNativeModule);
665 #endif
666             g_isLoadingModule = false;
667         }
668 
669         (void)pthread_mutex_unlock(&mutex_);
670     }
671     MoveApiAllowListCheckerPtr(apiAllowListChecker, nativeModule);
672 #ifdef ENABLE_HITRACE
673     FinishTrace(HITRACE_TAG_ACE);
674 #endif
675     HILOG_DEBUG("load native module %{public}s", (nativeModule == nullptr) ? "failed" : "success");
676     return nativeModule;
677 }
678 
CheckNativeListChanged(const NativeModule * cacheHeadNativeModule,const NativeModule * cacheTailNativeModule)679 bool NativeModuleManager::CheckNativeListChanged(
680     const NativeModule* cacheHeadNativeModule, const NativeModule* cacheTailNativeModule)
681 {
682     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
683     if (!cacheHeadNativeModule || !cacheTailNativeModule || !headNativeModule_ || !tailNativeModule_) {
684         return true;
685     }
686     if (strcmp(cacheHeadNativeModule->name, headNativeModule_->name) != 0 ||
687         strcmp(cacheTailNativeModule->name, tailNativeModule_->name) != 0) {
688         return true;
689     }
690 
691     return false;
692 }
GetNativeModulePath(const char * moduleName,const char * path,const char * relativePath,bool isAppModule,char nativeModulePath[][NAPI_PATH_MAX],int32_t pathLength)693 bool NativeModuleManager::GetNativeModulePath(const char* moduleName, const char* path,
694     const char* relativePath, bool isAppModule, char nativeModulePath[][NAPI_PATH_MAX], int32_t pathLength)
695 {
696 #ifdef WINDOWS_PLATFORM
697     const char* soPostfix = ".dll";
698     const char* zfix = "";
699     std::string sysPrefix("./module");
700     const char* abcfix = ".abc";
701     std::string sysAbcPrefix("./module");
702 #elif defined(MAC_PLATFORM)
703     const char* soPostfix = ".dylib";
704     const char* zfix = "";
705     std::string sysPrefix("./module");
706     const char* abcfix = ".abc";
707     std::string sysAbcPrefix("./module");
708 #elif defined(_ARM64_) || defined(SIMULATOR)
709     const char* soPostfix = ".so";
710     const char* zfix = ".z";
711     std::string sysPrefix("/system/lib64/module");
712     const char* abcfix = ".abc";
713     std::string sysAbcPrefix("/system/etc/abc");
714 #elif defined(LINUX_PLATFORM)
715     const char* soPostfix = ".so";
716     const char* zfix = "";
717     std::string sysPrefix("./module");
718     const char* abcfix = ".abc";
719     std::string sysAbcPrefix("./module");
720 #else
721     const char* soPostfix = ".so";
722     const char* zfix = ".z";
723     std::string sysPrefix("/system/lib/module");
724     const char* abcfix = ".abc";
725     std::string sysAbcPrefix("/system/etc/abc");
726 #endif
727 
728 #ifdef ANDROID_PLATFORM
729     isAppModule = true;
730 #endif
731     int32_t lengthOfModuleName = strlen(moduleName);
732     char dupModuleName[NAPI_PATH_MAX] = { 0 };
733     if (strcpy_s(dupModuleName, NAPI_PATH_MAX, moduleName) != 0) {
734         HILOG_ERROR("strcpy_s moduleName '%{public}s' failed", moduleName);
735         return false;
736     }
737 
738     const char* prefix = nullptr;
739     if (isAppModule && IsExistedPath(path)) {
740         appLibPathMapMutex_.lock();
741         prefix = appLibPathMap_[path];
742         appLibPathMapMutex_.unlock();
743 #ifdef ANDROID_PLATFORM
744         for (int32_t i = 0; i < lengthOfModuleName; i++) {
745             dupModuleName[i] = tolower(dupModuleName[i]);
746         }
747         if (prefix == nullptr) {
748             return false;
749         }
750         /*
751          * The requirement is to ensure the abc format file is placed in the path
752          * /data/user/0/com.example.myapplication/files/arkui-x/systemres/abc.
753          * Steps to follow:
754          * 1.	First, check if the /files/arkui-x directory exists.
755          * 2.	Verify that the original path consists of two paths separated by a colon (:).
756          * 3.	Identify whether /files/arkui-x is located in the portion before or after the colon.
757          * 4.	Extract and concatenate the appropriate part of the path to construct
758          *      the full abc file path for subsequent logic to access the file
759          */
760         std::string prefixStr(prefix);
761         const std::string arkuiKey = "/files/arkui-x";
762         std::size_t arkuiPos = prefixStr.find(arkuiKey);
763         if (arkuiPos != std::string::npos) {
764             std::size_t endPos = arkuiPos + arkuiKey.length();
765             std::size_t delimiterPos = prefixStr.find(':');
766             if (delimiterPos != std::string::npos) {
767                 sysAbcPrefix = (arkuiPos < delimiterPos)
768                                    ? prefixStr.substr(0, endPos) + "/systemres/abc"
769                                    : prefixStr.substr(delimiterPos + 1, endPos - (delimiterPos + 1)) +
770                                         "/systemres/abc";
771             } else {
772                 sysAbcPrefix = prefixStr.substr(0, endPos) + "/systemres/abc";
773             }
774         }
775 #endif
776     } else {
777         if (relativePath[0]) {
778             if (previewSearchPath_.empty()) {
779                 sysPrefix = sysPrefix + "/" + relativePath;
780             } else {
781                 sysPrefix = previewSearchPath_ + "/module";
782             }
783         }
784         prefix = sysPrefix.c_str();
785         for (int32_t i = 0; i < lengthOfModuleName; i++) {
786             dupModuleName[i] = tolower(dupModuleName[i]);
787         }
788 #ifdef IOS_PLATFORM
789         if (appLibPathMap_.find("default") != appLibPathMap_.end()) {
790             std::string sandboxPath(appLibPathMap_["default"]);
791             sysAbcPrefix = sandboxPath + "/systemres/abc";
792         }
793 #endif
794     }
795 
796     int32_t lengthOfPostfix = strlen(soPostfix);
797     if ((lengthOfModuleName > lengthOfPostfix) &&
798         (strcmp(dupModuleName + lengthOfModuleName - lengthOfPostfix, soPostfix) == 0)) {
799         if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s", prefix, dupModuleName) == -1) {
800             return false;
801         }
802         return true;
803     }
804 
805     char* lastDot = strrchr(dupModuleName, '.');
806     if (lastDot == nullptr) {
807         if (!isAppModule || !IsExistedPath(path)) {
808 #ifdef ANDROID_PLATFORM
809             if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
810                 return false;
811             }
812 #else
813             if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s%s",
814                 prefix, dupModuleName, zfix, soPostfix) == -1) {
815                 return false;
816             }
817 #endif
818             if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s_napi%s%s",
819                 prefix, dupModuleName, zfix, soPostfix) == -1) {
820                 return false;
821             }
822 
823             if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
824                 sysAbcPrefix.c_str(), dupModuleName, abcfix) == -1) {
825                 return false;
826             }
827         } else {
828 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
829     !defined(LINUX_PLATFORM)
830             if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
831                 return false;
832             }
833 #elif defined(ANDROID_PLATFORM)
834             std::string libPath;
835             int sprintfResult = 0;
836             std::string prefixStr = std::string(prefix);
837             std::size_t pos = prefixStr.find(':');
838             if (pos != std::string::npos) {
839                 sprintfResult = sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s%s",
840                     prefixStr.substr(0, pos).c_str(), dupModuleName, soPostfix);
841                 libPath = prefixStr.substr(pos + 1);
842             } else {
843                 sprintfResult = sprintf_s(nativeModulePath[1], pathLength, "lib%s%s", dupModuleName, soPostfix);
844                 libPath = prefixStr;
845             }
846             if (sprintfResult == -1) {
847                 return false;
848             }
849 #else
850             if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", prefix, dupModuleName, soPostfix) == -1) {
851                 return false;
852             }
853 #endif
854 #ifdef ANDROID_PLATFORM
855             if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", libPath.c_str(),
856                 dupModuleName, soPostfix) == -1) {
857                 return false;
858             }
859             char* lastUnderScore = strrchr(dupModuleName, '_');
860             const char* moduleNamePart = (lastUnderScore != nullptr) ? (lastUnderScore + 1) : dupModuleName;
861             if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
862                 sysAbcPrefix.c_str(), moduleNamePart, abcfix) == -1) {
863                 return false;
864             }
865 #endif
866         }
867     } else {
868         char* afterDot = lastDot + 1;
869         if (*afterDot == '\0') {
870             return false;
871         }
872         *lastDot = '\0';
873         lengthOfModuleName = strlen(dupModuleName);
874         for (int32_t i = 0; i < lengthOfModuleName; i++) {
875             if (*(dupModuleName + i) == '.') {
876                 *(dupModuleName + i) = '/';
877             }
878         }
879         if (!isAppModule || !IsExistedPath(path)) {
880             if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s%s",
881                 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
882                 return false;
883             }
884             if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s_napi%s%s",
885                 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
886                 return false;
887             }
888 #ifdef IOS_PLATFORM
889             if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
890                 sysAbcPrefix.c_str(), afterDot, abcfix) == -1) {
891                 return false;
892             }
893 #else
894             if (sprintf_s(nativeModulePath[2], pathLength, "%s/%s/%s%s", // 2 : Element index value
895                 sysAbcPrefix.c_str(), dupModuleName, afterDot, abcfix) == -1) {
896                 return false;
897             }
898 #endif
899         } else {
900 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
901     !defined(LINUX_PLATFORM)
902             if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", afterDot, soPostfix) == -1) {
903                 return false;
904             }
905 #else
906             if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s",
907                 prefix, dupModuleName, afterDot, soPostfix) == -1) {
908                 return false;
909             }
910 #endif
911 #ifdef ANDROID_PLATFORM
912             if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s%s",
913                 prefix, moduleName, afterDot, soPostfix) == -1) {
914                 return false;
915             }
916 #endif
917         }
918     }
919     return true;
920 }
921 
LoadModuleLibrary(std::string & moduleKey,const char * path,const char * pathKey,const bool isAppModule,std::string & errInfo,uint32_t & errReason)922 LIBHANDLE NativeModuleManager::LoadModuleLibrary(std::string& moduleKey, const char* path,
923     const char* pathKey, const bool isAppModule, std::string& errInfo, uint32_t& errReason)
924 {
925     if (strlen(path) == 0) {
926         errInfo += "load module " + moduleKey  + " failed. module path is empty";
927         HILOG_ERROR("%{public}s", errInfo.c_str());
928         return nullptr;
929     }
930 
931     LIBHANDLE lib = nullptr;
932 
933     HILOG_DEBUG("path: %{public}s, pathKey: %{public}s, isAppModule: %{public}d", path, pathKey, isAppModule);
934 #ifdef ENABLE_HITRACE
935     StartTrace(HITRACE_TAG_ACE, path);
936 #endif
937 #if defined(WINDOWS_PLATFORM)
938     if (CheckModuleExist(path) == false) {
939         errReason = MODULE_NOT_EXIST;
940         return nullptr;
941     }
942     lib = LoadLibrary(path);
943     if (lib == nullptr) {
944         errInfo += "load module failed. " + std::to_string(GetLastError());
945         HILOG_WARN("%{public}s", errInfo.c_str());
946     }
947 #elif defined(MAC_PLATFORM) || defined(__BIONIC__) || defined(LINUX_PLATFORM)
948 #ifndef ANDROID_PLATFORM
949     if (CheckModuleExist(path) == false) {
950         errReason = MODULE_NOT_EXIST;
951         return nullptr;
952     }
953 #endif
954     lib = dlopen(path, RTLD_LAZY);
955     if (lib == nullptr) {
956         char* dlerr = dlerror();
957         auto dlerrMsg = dlerr != nullptr ? dlerr : "dlerror msg is empty";
958         errInfo += "load module failed. " +  std::string(dlerrMsg);
959     }
960 
961 #elif defined(IOS_PLATFORM)
962     lib = nullptr;
963 #else
964     if (isAppModule && IsExistedPath(pathKey)) {
965         Dl_namespace ns = nsMap_[pathKey];
966         lib = dlopen_ns(&ns, path, RTLD_LAZY);
967     } else if (access(path, F_OK) == 0) {
968         lib = dlopen(path, RTLD_LAZY);
969     }
970     if (lib == nullptr) {
971         char* dlerr = dlerror();
972         auto dlerrMsg = dlerr != nullptr ? dlerr :
973             "Error loading path " + std::string(path) + ":No such file or directory";
974         errInfo += "load app module failed. " +  std::string(dlerrMsg);
975     }
976 #endif
977 #ifdef ENABLE_HITRACE
978     FinishTrace(HITRACE_TAG_ACE);
979 #endif
980     EmplaceModuleLib(moduleKey, lib);
981 
982     return lib;
983 }
984 
GetFileBuffer(const std::string & filePath,const std::string & moduleKey,size_t & len)985 const uint8_t* NativeModuleManager::GetFileBuffer(const std::string& filePath,
986     const std::string& moduleKey, size_t &len)
987 {
988     const uint8_t* lib = nullptr;
989     std::ifstream inFile(filePath, std::ios::ate | std::ios::binary);
990     if (!inFile.is_open()) {
991         HILOG_ERROR("%{public}s is not existed.", filePath.c_str());
992         return lib;
993     }
994     len = static_cast<size_t>(inFile.tellg());
995     std::string abcModuleKey = moduleKey;
996     lib = GetBufferHandle(abcModuleKey);
997     if (lib != nullptr) {
998         HILOG_DEBUG("get native abc handle success. moduleKey is %{public}s", moduleKey.c_str());
999         inFile.close();
1000         return lib;
1001     }
1002 
1003     std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
1004     inFile.seekg(0);
1005     inFile.read(reinterpret_cast<char*>(buffer.get()), len);
1006     inFile.close();
1007     lib = buffer.release();
1008     EmplaceModuleBuffer(abcModuleKey, lib);
1009     return lib;
1010 }
1011 
UnloadModuleLibrary(LIBHANDLE handle)1012 bool NativeModuleManager::UnloadModuleLibrary(LIBHANDLE handle)
1013 {
1014     if (handle == nullptr) {
1015         HILOG_WARN("handle is nullptr");
1016         return false;
1017     }
1018 #if !defined(WINDOWS_PLATFORM) && !defined(IOS_PLATFORM)
1019     if (!dlclose(handle)) {
1020         return true;
1021     }
1022     char* dlerr = dlerror();
1023     auto dlerrMsg = dlerr != nullptr ? dlerr : "dlerror msg is empty";
1024     HILOG_WARN("dlclose failed: %{public}s", dlerrMsg);
1025 #endif
1026     return false;
1027 }
1028 
CheckModuleExist(const char * modulePath)1029 bool NativeModuleManager::CheckModuleExist(const char* modulePath)
1030 {
1031     if (modulePath) {
1032         std::ifstream inFile(modulePath, std::ios::ate | std::ios::binary);
1033         if (inFile.is_open()) {
1034             inFile.close();
1035             return true;
1036         }
1037     }
1038     return false;
1039 }
1040 
FindNativeModuleByDisk(const char * moduleName,const char * path,const char * relativePath,bool internal,const bool isAppModule,std::string & errInfo,char nativeModulePath[][NAPI_PATH_MAX],NativeModule * cacheNativeModule)1041 NativeModule* NativeModuleManager::FindNativeModuleByDisk(const char* moduleName, const char* path,
1042     const char* relativePath, bool internal, const bool isAppModule, std::string& errInfo,
1043     char nativeModulePath[][NAPI_PATH_MAX], NativeModule* cacheNativeModule)
1044 {
1045     std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
1046     if (moduleLoadChecker_ && !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker, isAppModule)) {
1047         errInfo = "module " + std::string(moduleName) + " is in blocklist, loading prohibited";
1048         HILOG_WARN("%{public}s", errInfo.c_str());
1049         return nullptr;
1050     }
1051 
1052     std::string moduleKey(moduleName);
1053     if (isAppModule) {
1054         moduleKey = path;
1055         moduleKey = moduleKey + '/' + moduleName;
1056     }
1057     loadingModuleName_ = moduleKey;
1058 
1059     // load primary module path first
1060     char* loadPath = nativeModulePath[0];
1061     HILOG_DEBUG("moduleName is %{public}s. get primary module path is %{public}s", moduleName, loadPath);
1062     uint32_t errReason0 = MODULE_LOAD_SUCCESS;
1063     errInfo = "First attempt: ";
1064     LIBHANDLE lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule, errInfo, errReason0);
1065     if (lib == nullptr) {
1066         errInfo += "\nSecond attempt: ";
1067         loadPath = nativeModulePath[1];
1068         HILOG_DEBUG("try to load secondary module path: %{public}s", loadPath);
1069         uint32_t errReason1 = MODULE_LOAD_SUCCESS;
1070         lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule, errInfo, errReason1);
1071         if (lib == nullptr && errReason0 == MODULE_NOT_EXIST && errReason1 == MODULE_NOT_EXIST) {
1072             HILOG_ERROR("%{public}s does not exist, errMsg %{public}s", nativeModulePath[0], errInfo.c_str());
1073         }
1074     }
1075 
1076     //Maintain compatibility
1077     if (lib == nullptr && cacheNativeModule != nullptr) {
1078         HILOG_DEBUG("Maintain compatibility.");
1079         return cacheNativeModule;
1080     }
1081 
1082     const uint8_t* abcBuffer = nullptr;
1083     size_t len = 0;
1084     if (lib == nullptr) {
1085         loadPath = nativeModulePath[2]; // 2 : Element index value
1086         HILOG_DEBUG("try to load abc module path: %{public}s", loadPath);
1087         abcBuffer = GetFileBuffer(loadPath, moduleKey, len);
1088         if (!abcBuffer) {
1089             errInfo += "\ntry to load abc file from " + std::string(loadPath) + " failed";
1090             HILOG_ERROR("%{public}s", errInfo.c_str());
1091             return nullptr;
1092         }
1093     }
1094 
1095     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1096     if (tailNativeModule_ && !abcBuffer) {
1097         const char* moduleName = strdup(moduleKey.c_str());
1098         if (moduleName == nullptr) {
1099             HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleKey.c_str());
1100             return nullptr;
1101         }
1102 
1103         tailNativeModule_->moduleName = moduleName;
1104         tailNativeModule_->systemFilePath = strdup(loadPath);
1105         if (strcmp(tailNativeModule_->moduleName, tailNativeModule_->name)) {
1106             HILOG_WARN("mismatch: moduleName is %{public}s, name is %{public}s",
1107                 tailNativeModule_->moduleName, tailNativeModule_->name);
1108             HILOG_WARN("suggestion: keep .nm_modname the same as moduleName imported or required");
1109         }
1110     }
1111 
1112     if (!internal) {
1113         char symbol[NAPI_PATH_MAX] = { 0 };
1114         if (sprintf_s(symbol, sizeof(symbol), "NAPI_%s_GetABCCode", moduleKey.c_str()) == -1) {
1115             if (lib != nullptr) {
1116                 LIBFREE(lib);
1117             }
1118             errInfo = "sprintf symbol NAPI_" + moduleKey + "_GetABCCode failed";
1119             HILOG_ERROR("%{public}s", errInfo.c_str());
1120             return nullptr;
1121         }
1122 
1123         // replace '.' and '/' with '_'
1124         for (char* p = strchr(symbol, '.'); p != nullptr; p = strchr(p + 1, '.')) {
1125             *p = '_';
1126         }
1127         for (char* p = strchr(symbol, '/'); p != nullptr; p = strchr(p + 1, '/')) {
1128             *p = '_';
1129         }
1130 
1131         if (lib != nullptr) {
1132             auto getJSCode = reinterpret_cast<GetJSCodeCallback>(LIBSYM(lib, symbol));
1133             if (getJSCode == nullptr) {
1134                 HILOG_DEBUG("ignore: no %{public}s in %{public}s", symbol, loadPath);
1135                 MoveApiAllowListCheckerPtr(apiAllowListChecker, tailNativeModule_);
1136                 return tailNativeModule_;
1137             }
1138             const char* buf = nullptr;
1139             int bufLen = 0;
1140             getJSCode(&buf, &bufLen);
1141             if (tailNativeModule_) {
1142                 HILOG_DEBUG("get js code from module: bufLen: %{public}d", bufLen);
1143                 tailNativeModule_->jsCode = buf;
1144                 tailNativeModule_->jsCodeLen = bufLen;
1145             }
1146         } else {
1147             RegisterByBuffer(moduleKey, abcBuffer, len);
1148             tailNativeModule_->systemFilePath = strdup(loadPath);
1149         }
1150     }
1151     if (tailNativeModule_) {
1152         tailNativeModule_->moduleLoaded = true;
1153         if (tailNativeModule_->name && tailNativeModule_->moduleName) {
1154             HILOG_DEBUG("last native info: name is %{public}s, moduleName is %{public}s",
1155                 tailNativeModule_->name, tailNativeModule_->moduleName);
1156         }
1157         MoveApiAllowListCheckerPtr(apiAllowListChecker, tailNativeModule_);
1158     }
1159     return tailNativeModule_;
1160 }
1161 
RegisterByBuffer(const std::string & moduleKey,const uint8_t * abcBuffer,size_t len)1162 void NativeModuleManager::RegisterByBuffer(const std::string& moduleKey, const uint8_t* abcBuffer, size_t len)
1163 {
1164     HILOG_DEBUG("native module name is '%{public}s'", moduleKey.c_str());
1165     if (!CreateTailNativeModule()) {
1166         HILOG_ERROR("create tail nativeModule failed");
1167         return;
1168     }
1169 
1170     char *moduleName = strdup(moduleKey.c_str());
1171     if (moduleName == nullptr) {
1172         HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleKey.c_str());
1173         return;
1174     }
1175     tailNativeModule_->moduleName = moduleName;
1176     tailNativeModule_->name = strdup(moduleName);
1177     if (tailNativeModule_->name == nullptr) {
1178         HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleName);
1179         free(moduleName);
1180         tailNativeModule_->moduleName = nullptr;
1181         return;
1182     }
1183     tailNativeModule_->jsABCCode = abcBuffer;
1184     tailNativeModule_->jsCodeLen = static_cast<int32_t>(len);
1185     tailNativeModule_->next = nullptr;
1186 
1187     HILOG_INFO("Register by buffer success. module name is '%{public}s'", tailNativeModule_->moduleName);
1188 }
1189 
RemoveNativeModuleByCache(const std::string & moduleKey)1190 bool NativeModuleManager::RemoveNativeModuleByCache(const std::string& moduleKey)
1191 {
1192     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1193 
1194     if (headNativeModule_ == nullptr) {
1195         HILOG_WARN("NativeModule list is empty");
1196         return false;
1197     }
1198 
1199     NativeModule* nativeModule = headNativeModule_;
1200     if (!strcasecmp(nativeModule->moduleName, moduleKey.c_str())) {
1201         if (headNativeModule_ == tailNativeModule_) {
1202             tailNativeModule_ = nullptr;
1203         }
1204         headNativeModule_ = headNativeModule_->next;
1205         delete[] nativeModule->name;
1206         if (nativeModule->moduleName) {
1207             delete[] nativeModule->moduleName;
1208         }
1209         if (headNativeModule_->jsABCCode) {
1210             delete[] headNativeModule_->jsABCCode;
1211         }
1212         delete nativeModule;
1213         HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
1214         return true;
1215     }
1216 
1217     bool moduleDeleted = false;
1218     NativeModule* prev = headNativeModule_;
1219     NativeModule* curr = prev->next;
1220     while (curr != nullptr) {
1221         if (!strcasecmp(curr->moduleName, moduleKey.c_str())) {
1222             if (curr == tailNativeModule_) {
1223                 tailNativeModule_ = prev;
1224             }
1225             prev->next = curr->next;
1226             delete[] curr->name;
1227             if (curr->moduleName) {
1228                 delete[] curr->moduleName;
1229             }
1230             if (curr->jsABCCode) {
1231                 delete[] curr->jsABCCode;
1232             }
1233             delete curr;
1234             HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
1235             moduleDeleted = true;
1236             break;
1237         }
1238         prev = prev->next;
1239         curr = prev->next;
1240     }
1241 
1242     return moduleDeleted;
1243 }
1244 
FindNativeModuleByCache(const char * moduleName,char nativeModulePath[][NAPI_PATH_MAX],NativeModule * & cacheNativeModule,NativeModuleHeadTailStruct & cacheHeadTailStruct)1245 NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName,
1246                                                            char nativeModulePath[][NAPI_PATH_MAX],
1247                                                            NativeModule*& cacheNativeModule,
1248                                                            NativeModuleHeadTailStruct& cacheHeadTailStruct)
1249 {
1250     NativeModule* result = nullptr;
1251 
1252     std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1253     cacheNativeModule = nullptr;
1254     for (NativeModule* temp = headNativeModule_; temp != nullptr; temp = temp->next) {
1255         if ((temp->moduleName && !strcmp(temp->moduleName, moduleName))
1256             || !strcasecmp(temp->name, moduleName)) {
1257             int label = 0;
1258 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
1259             while (label < NATIVE_PATH_NUMBER && strcmp(temp->systemFilePath, nativeModulePath[label])) {
1260                 label++;
1261             }
1262 #endif
1263             if (label < NATIVE_PATH_NUMBER || !strcmp(temp->systemFilePath, "")) {
1264                 result = temp;
1265                 break;
1266             } else {
1267                 HILOG_WARN("moduleName '%{public}s' is in different path", moduleName);
1268                 cacheNativeModule = temp;
1269             }
1270         }
1271     }
1272     cacheHeadTailStruct.headNativeModule = headNativeModule_;
1273     cacheHeadTailStruct.tailNativeModule = tailNativeModule_;
1274 
1275     return result;
1276 }
1277 
IsExistedPath(const char * pathKey) const1278 bool NativeModuleManager::IsExistedPath(const char* pathKey) const
1279 {
1280     HILOG_DEBUG("pathKey is '%{public}s'", pathKey);
1281     std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
1282     return pathKey && appLibPathMap_.find(pathKey) != appLibPathMap_.end();
1283 }
1284 
SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> & moduleCheckerDelegate)1285 void NativeModuleManager::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate)
1286 {
1287     HILOG_DEBUG("enter");
1288     if (!moduleLoadChecker_) {
1289         HILOG_ERROR("SetModuleLoadChecker failed, moduleLoadChecker_ is nullptr");
1290         return;
1291     }
1292     moduleLoadChecker_->SetDelegate(moduleCheckerDelegate);
1293 }
1294 
SetPreviewSearchPath(const std::string & previewSearchPath)1295 void NativeModuleManager::SetPreviewSearchPath(const std::string& previewSearchPath)
1296 {
1297     HILOG_DEBUG("previewSearchPath is '%{public}s'", previewSearchPath.c_str());
1298     previewSearchPath_ = previewSearchPath;
1299 }
1300