1010#include < fcntl.h> // "open" flags
1111#include < android/looper.h> // ALooper
1212#include < dlfcn.h>
13+ #include < limits.h>
1314
1415#include < aml.h>
1516#include < defines.h>
3233#include < interfaces.h>
3334#include < modslist.h>
3435
36+ #ifndef AML_PATH_MAX
37+ #ifdef PATH_MAX
38+ #define AML_PATH_MAX PATH_MAX
39+ #else
40+ #define AML_PATH_MAX 4096
41+ #endif
42+ #endif
43+
3544pid_t g_MainThreadID = 0 ;
3645bool g_bShowUpdatedToast, g_bShowUpdateFailedToast, g_bEnableFileDownloads;
3746bool g_bCrashAML, g_bNoMods, g_bSimplerCrashLog = false , g_bNoSPInLog, g_bNoModsInLog, g_bMLSOnlyManualSaves, g_bDumpAllThreads, g_bEHUnwind, g_bMoreRegsInfo, g_bUnixBacktrace = false ;
@@ -181,14 +190,43 @@ inline bool HasFakeAppName()
181190 return (g_szFakeAppName[0 ] != 0 && strlen (g_szFakeAppName) > 5 );
182191}
183192
193+ static bool CopyJStringUTF (JNIEnv* env, jstring str, char * out, size_t outLen, bool lowercase = false )
194+ {
195+ if (!env || !str || !out || outLen == 0 ) return false ;
196+
197+ const char * tmp = env->GetStringUTFChars (str, NULL );
198+ if (!tmp)
199+ {
200+ if (env->ExceptionCheck ()) env->ExceptionClear ();
201+ return false ;
202+ }
203+
204+ size_t i = 0 ;
205+ if (lowercase)
206+ {
207+ for (; tmp[i] != 0 && i < outLen - 1 ; ++i)
208+ {
209+ out[i] = (char )tolower ((unsigned char )tmp[i]);
210+ }
211+ out[i] = 0 ;
212+ }
213+ else
214+ {
215+ snprintf (out, outLen, " %s" , tmp);
216+ }
217+
218+ env->ReleaseStringUTFChars (str, tmp);
219+ return true ;
220+ }
221+
184222typedef const char * (*SpecificGameFn)();
185223void LoadMods (const char * path)
186224{
187225 ModInfo* pModInfo = NULL ;
188226 SpecificGameFn maybeINeedAGame = NULL ;
189227 GetModInfoFn modInfoFn = NULL ;
190228
191- char buf[256 ], dataBuf[256 ];
229+ char buf[AML_PATH_MAX ], dataBuf[AML_PATH_MAX ];
192230 DIR * dir = opendir (path);
193231 if (dir != NULL )
194232 {
@@ -205,8 +243,13 @@ void LoadMods(const char* path)
205243 // logger->Error("File %s is not a mod, atleast it is NOT .SO file!", diread->d_name);
206244 continue ;
207245 }
208- snprintf (buf, sizeof (buf), " %s/%s" , path, diread->d_name );
209- snprintf (dataBuf, sizeof (dataBuf), " %s/%s" , g_szDataDir, diread->d_name );
246+ int srcLen = snprintf (buf, sizeof (buf), " %s/%s" , path, diread->d_name );
247+ int tmpLen = snprintf (dataBuf, sizeof (dataBuf), " %s/%s" , g_szDataDir, diread->d_name );
248+ if (srcLen < 0 || srcLen >= (int )sizeof (buf) || tmpLen < 0 || tmpLen >= (int )sizeof (dataBuf))
249+ {
250+ logger->Error (" Skipping mod %s: path is too long" , diread->d_name );
251+ continue ;
252+ }
210253 // unlink(dataBuf);
211254 chmod (dataBuf, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP ); // XMDS
212255 int removeStatus = remove (dataBuf);
@@ -226,27 +269,36 @@ void LoadMods(const char* path)
226269 continue ;
227270 }
228271
272+ bool keepLoaded = false ;
229273 modInfoFn = (GetModInfoFn)dlsym (handle, " __GetModInfo" );
230274 if (modInfoFn != NULL )
231275 {
232276 pModInfo = modInfoFn ();
233- maybeINeedAGame = (SpecificGameFn)dlsym (handle, " __INeedASpecificGame" );
234- if (maybeINeedAGame != NULL && strcmp (maybeINeedAGame (), gameName) != 0 )
277+ if (pModInfo == NULL )
235278 {
236- logger->Error (" Mod (GUID %s) built for the game %s!" , pModInfo->GUID (), maybeINeedAGame ());
237- goto nextMod;
279+ logger->Error (" Mod %s returned NULL from __GetModInfo!" , diread->d_name );
238280 }
239- if (!modlist-> AddMod (pModInfo, handle, buf))
281+ else
240282 {
241- logger->Error (" Mod (GUID %s) is already loaded!" , pModInfo->GUID ());
242- goto nextMod;
283+ maybeINeedAGame = (SpecificGameFn)dlsym (handle, " __INeedASpecificGame" );
284+ const char * requiredGame = maybeINeedAGame ? maybeINeedAGame () : NULL ;
285+ if (requiredGame != NULL && requiredGame[0 ] != 0 && strcmp (requiredGame, gameName) != 0 )
286+ {
287+ logger->Error (" Mod (GUID %s) built for the game %s!" , pModInfo->GUID (), requiredGame);
288+ }
289+ else if (!modlist->AddMod (pModInfo, handle, buf))
290+ {
291+ logger->Error (" Mod (GUID %s) is already loaded!" , pModInfo->GUID ());
292+ }
293+ else
294+ {
295+ logger->Info (" Mod (GUID %s) has been preprocessed." , pModInfo->GUID ());
296+ keepLoaded = true ;
297+ }
243298 }
244-
245- logger->Info (" Mod (GUID %s) has been preprocessed." , pModInfo->GUID ());
246299 }
247- else
300+ if (!keepLoaded)
248301 {
249- nextMod:
250302 dlclose (handle);
251303 }
252304 // unlink(dataBuf);
@@ -310,13 +362,19 @@ jobject GetCurrentContext()
310362 if (!env) return NULL ;
311363
312364 jclass activityThread = env->FindClass (" android/app/ActivityThread" );
365+ if (!activityThread) { if (env->ExceptionCheck ()) env->ExceptionClear (); return NULL ; }
313366 jmethodID currentActivityThread = env->GetStaticMethodID (activityThread, " currentActivityThread" , " ()Landroid/app/ActivityThread;" );
367+ if (!currentActivityThread) { if (env->ExceptionCheck ()) env->ExceptionClear (); env->DeleteLocalRef (activityThread); return NULL ; }
314368 jobject activityThreadObj = env->CallStaticObjectMethod (activityThread, currentActivityThread);
369+ if (env->ExceptionCheck ()) env->ExceptionClear ();
370+ if (!activityThreadObj) { env->DeleteLocalRef (activityThread); return NULL ; }
315371 jmethodID getApplication = env->GetMethodID (activityThread, " getApplication" , " ()Landroid/app/Application;" );
372+ if (!getApplication) { if (env->ExceptionCheck ()) env->ExceptionClear (); env->DeleteLocalRef (activityThreadObj); env->DeleteLocalRef (activityThread); return NULL ; }
316373
317374 jobject localContext = env->CallObjectMethod (activityThreadObj, getApplication);
375+ if (env->ExceptionCheck ()) env->ExceptionClear ();
318376 if (localContext) g_GlobalContext = env->NewGlobalRef (localContext);
319- env->DeleteLocalRef (localContext);
377+ if (localContext) env->DeleteLocalRef (localContext);
320378 env->DeleteLocalRef (activityThreadObj);
321379 env->DeleteLocalRef (activityThread);
322380 return g_GlobalContext;
@@ -439,7 +497,7 @@ void StartAMLRightNow(const char* libName1 = NULL, const char* libName2 = NULL)
439497 }
440498
441499 logger->SetTag (" AndroidModLoader" );
442- const char * szTmp; jstring jTmp;
500+ jstring jTmp;
443501
444502 /* JNI Environment */
445503 if (g_pJavaVM->GetEnv (reinterpret_cast <void **>(&g_env), JNI_VERSION_1_6 ) != JNI_OK )
@@ -450,6 +508,11 @@ void StartAMLRightNow(const char* libName1 = NULL, const char* libName2 = NULL)
450508
451509 /* Application Context */
452510 jobject localContext = ::GetGlobalContext (g_env);
511+ if (localContext == NULL )
512+ {
513+ logger->Error (" Failed to resolve Android application context." );
514+ return ;
515+ }
453516 appContext = g_env->NewGlobalRef (localContext);
454517 g_env->DeleteLocalRef (localContext);
455518 if (appContext == NULL )
@@ -485,23 +548,25 @@ void StartAMLRightNow(const char* libName1 = NULL, const char* libName2 = NULL)
485548 /* Internal Storage */
486549 jobject storageDir = GetStorageDir (g_env);
487550 jTmp = GetAbsolutePath (g_env, storageDir);
488- szTmp = g_env->GetStringUTFChars (jTmp, NULL );
489- snprintf (g_szInternalStoragePath, sizeof (g_szInternalStoragePath), " %s" , szTmp);
490- g_env->ReleaseStringUTFChars (jTmp, szTmp);
491- g_env->DeleteLocalRef (jTmp);
492- g_env->DeleteLocalRef (storageDir);
551+ if (!CopyJStringUTF (g_env, jTmp, g_szInternalStoragePath, sizeof (g_szInternalStoragePath)))
552+ {
553+ logger->Error (" Failed to determine internal storage path." );
554+ if (jTmp) g_env->DeleteLocalRef (jTmp);
555+ if (storageDir) g_env->DeleteLocalRef (storageDir);
556+ return ;
557+ }
558+ if (jTmp) g_env->DeleteLocalRef (jTmp);
559+ if (storageDir) g_env->DeleteLocalRef (storageDir);
493560
494561 /* Package Name */
495- int i = 0 ;
496562 jTmp = GetPackageName (g_env, appContext);
497- szTmp = g_env->GetStringUTFChars (jTmp, NULL );
498- while (szTmp[i] != 0 && i < sizeof (g_szAppName)-1 )
499- {
500- g_szAppName[i] = tolower (szTmp[i]);
501- ++i;
502- } g_szAppName[i] = 0 ;
503- g_env->ReleaseStringUTFChars (jTmp, szTmp);
504- g_env->DeleteLocalRef (jTmp);
563+ if (!CopyJStringUTF (g_env, jTmp, g_szAppName, sizeof (g_szAppName), true ))
564+ {
565+ logger->Error (" Failed to determine package name." );
566+ if (jTmp) g_env->DeleteLocalRef (jTmp);
567+ return ;
568+ }
569+ if (jTmp) g_env->DeleteLocalRef (jTmp);
505570 logger->Info (" Determined app info: %s" , g_szAppName);
506571
507572 #ifdef FASTMAN92_CODE
@@ -546,11 +611,15 @@ void StartAMLRightNow(const char* libName1 = NULL, const char* libName2 = NULL)
546611 /* root/data/data Folder */
547612 jobject filesDir = GetFilesDir (g_env, appContext);
548613 jstring filesPath = GetAbsolutePath (g_env, filesDir);
549- szTmp = g_env->GetStringUTFChars (filesPath, NULL );
550- snprintf (g_szDataDirPath, sizeof (g_szDataDirPath), " %s" , szTmp);
551- g_env->ReleaseStringUTFChars (filesPath, szTmp);
552- g_env->DeleteLocalRef (filesPath);
553- g_env->DeleteLocalRef (filesDir);
614+ if (!CopyJStringUTF (g_env, filesPath, g_szDataDirPath, sizeof (g_szDataDirPath)))
615+ {
616+ logger->Error (" Failed to determine app data path." );
617+ if (filesPath) g_env->DeleteLocalRef (filesPath);
618+ if (filesDir) g_env->DeleteLocalRef (filesDir);
619+ return ;
620+ }
621+ if (filesPath) g_env->DeleteLocalRef (filesPath);
622+ if (filesDir) g_env->DeleteLocalRef (filesDir);
554623
555624 /* AML Config */
556625 logger->Info (" Reading core config..." );
@@ -667,7 +736,7 @@ void StartAMLRightNow(const char* libName1 = NULL, const char* libName2 = NULL)
667736 {
668737 for (int i = 0 ; i < g_nEnableNews; ++i)
669738 {
670- aml->ShowToast (true , g_szNewsString);
739+ aml->ShowToast (true , " %s " , g_szNewsString);
671740 }
672741
673742 newsBuf[16 ] = ' |' ; // Anti- news spamming :p
@@ -731,13 +800,13 @@ extern "C" JNIEXPORT void JNICALL Java_net_rusjj_amlcore_earlyLaunchAMLCore(JNIE
731800{
732801 // Early stage starting
733802 // LAUNCHES lib1 AND lib2 BY ITSELF!!!
734- const char * szLib1 = env->GetStringUTFChars (lib1, NULL );
735- const char * szLib2 = env->GetStringUTFChars (lib2, NULL );
803+ const char * szLib1 = lib1 ? env->GetStringUTFChars (lib1, NULL ) : NULL ;
804+ const char * szLib2 = lib2 ? env->GetStringUTFChars (lib2, NULL ) : NULL ;
736805
737806 StartAMLRightNow (szLib1, szLib2);
738807
739- env->ReleaseStringUTFChars (lib1, szLib1);
740- env->ReleaseStringUTFChars (lib2, szLib2);
808+ if (lib1 && szLib1) env->ReleaseStringUTFChars (lib1, szLib1);
809+ if (lib2 && szLib2) env->ReleaseStringUTFChars (lib2, szLib2);
741810}
742811
743812static ALooper* g_pJavaUILooper = NULL ;
0 commit comments