1010 ******************************************************************************/
1111package soot .jimple .infoflow .android .entryPointCreators ;
1212
13+ import java .util .ArrayList ;
1314import java .util .Collection ;
1415import java .util .Collections ;
1516import java .util .HashMap ;
2324import org .slf4j .LoggerFactory ;
2425
2526import soot .Body ;
27+ import soot .Hierarchy ;
2628import soot .Local ;
2729import soot .Modifier ;
2830import soot .RefType ;
2931import soot .Scene ;
3032import soot .SootClass ;
3133import soot .SootField ;
3234import soot .SootMethod ;
35+ import soot .Type ;
3336import soot .Unit ;
37+ import soot .UnitPatchingChain ;
38+ import soot .Value ;
39+ import soot .jimple .AssignStmt ;
3440import soot .jimple .IfStmt ;
41+ import soot .jimple .InvokeStmt ;
3542import soot .jimple .Jimple ;
3643import soot .jimple .NopStmt ;
3744import soot .jimple .NullConstant ;
45+ import soot .jimple .StaticFieldRef ;
3846import soot .jimple .Stmt ;
3947import soot .jimple .infoflow .android .entryPointCreators .AndroidEntryPointUtils .ComponentType ;
4048import soot .jimple .infoflow .android .entryPointCreators .components .AbstractComponentEntryPointCreator ;
5058import soot .jimple .infoflow .cfg .LibraryClassPatcher ;
5159import soot .jimple .infoflow .data .SootMethodAndClass ;
5260import soot .jimple .infoflow .entryPointCreators .IEntryPointCreator ;
61+ import soot .jimple .infoflow .entryPointCreators .SimulatedCodeElementTag ;
5362import soot .jimple .infoflow .util .SootMethodRepresentationParser ;
5463import soot .jimple .infoflow .util .SystemClassHandler ;
5564import soot .jimple .toolkits .scalar .NopEliminator ;
@@ -92,6 +101,8 @@ public class AndroidEntryPointCreator extends AbstractAndroidEntryPointCreator i
92101
93102 private Collection <SootClass > components ;
94103
104+ private MultiMap <SootMethod , Stmt > javascriptInterfaceStmts ;
105+
95106 /**
96107 * Creates a new instance of the {@link AndroidEntryPointCreator} class and
97108 * registers a list of classes to be automatically scanned for Android lifecycle
@@ -305,6 +316,7 @@ protected SootMethod createDummyMainInternal() {
305316 addApplicationCallbackMethods ();
306317 createIfStmt (beforeAppCallbacks );
307318 }
319+ createJavascriptCallbacks ();
308320
309321 createIfStmt (outerStartStmt );
310322
@@ -326,6 +338,60 @@ protected SootMethod createDummyMainInternal() {
326338 return mainMethod ;
327339 }
328340
341+ private void createJavascriptCallbacks () {
342+ Jimple j = Jimple .v ();
343+ Hierarchy h = Scene .v ().getActiveHierarchy ();
344+ for (SootMethod m : javascriptInterfaceStmts .keySet ()) {
345+ Set <Stmt > statements = javascriptInterfaceStmts .get (m );
346+ for (Stmt s : statements ) {
347+ UnitPatchingChain units = m .retrieveActiveBody ().getUnits ();
348+ Stmt succ = (Stmt ) units .getSuccOf (s );
349+ SootField f = null ;
350+ Value arg = s .getInvokeExpr ().getArg (0 );
351+ if (succ .getTag (SimulatedCodeElementTag .TAG_NAME ) != null ) {
352+ if (succ instanceof AssignStmt ) {
353+ AssignStmt assign = (AssignStmt ) succ ;
354+ if (assign .getRightOp () == arg && assign .getLeftOp () instanceof StaticFieldRef ) {
355+ f = ((StaticFieldRef ) assign .getLeftOp ()).getField ();
356+ }
357+ }
358+ }
359+ if (f == null ) {
360+ //create field
361+ f = createField (arg .getType (), "jsInterface" );
362+ AssignStmt assign = j .newAssignStmt (j .newStaticFieldRef (f .makeRef ()), arg );
363+ assign .addTag (SimulatedCodeElementTag .TAG );
364+ units .insertAfter (assign , s );
365+ }
366+
367+ Local l = j .newLocal (f .getName (), f .getType ());
368+ body .getLocals ().add (l );
369+ Stmt assignF = j .newAssignStmt (l , j .newStaticFieldRef (f .makeRef ()));
370+ body .getUnits ().add (assignF );
371+ SootClass cbtype = ((RefType ) f .getType ()).getSootClass ();
372+ List <SootClass > allPossibleImpls ;
373+ if (cbtype .isInterface ()) {
374+ allPossibleImpls = h .getImplementersOf (cbtype );
375+ } else {
376+ allPossibleImpls = h .getSubclassesOfIncluding (cbtype );
377+ }
378+ for (SootClass c : allPossibleImpls ) {
379+ for (SootMethod cbm : c .getMethods ()) {
380+ if (AndroidEntryPointUtils .isCallableFromJS (cbm )) {
381+ List <Value > args = new ArrayList <>();
382+ for (Type t : cbm .getParameterTypes ())
383+ args .add (getSimpleDefaultValue (t ));
384+ InvokeStmt st = j .newInvokeStmt (j .newVirtualInvokeExpr (l , cbm .makeRef (), args ));
385+ body .getUnits ().add (st );
386+ }
387+ }
388+ }
389+ createIfStmt (assignF );
390+
391+ }
392+ }
393+ }
394+
329395 /**
330396 * Checks whether a lifecycle call should be added to the given SootClass,
331397 * designed to be overridden by different implementations
@@ -392,20 +458,24 @@ private void initializeApplicationClass() {
392458 baseName = baseName .substring (baseName .lastIndexOf ("." ) + 1 );
393459
394460 // Generate a fresh field name
395- SootClass dummyMainClass = mainMethod .getDeclaringClass ();
396- int idx = 0 ;
397- String fieldName = baseName ;
398- while (dummyMainClass .declaresFieldByName (fieldName )) {
399- fieldName = baseName + "_" + idx ;
400- idx ++;
401- }
402- SootField fld = Scene .v ().makeSootField (fieldName , RefType .v (callbackClass ),
403- Modifier .PRIVATE | Modifier .STATIC );
404- mainMethod .getDeclaringClass ().addField (fld );
461+ SootField fld = createField (RefType .v (callbackClass ), baseName );
405462 callbackClassToField .put (callbackClass , fld );
406463 }
407464 }
408465
466+ protected SootField createField (Type type , String baseName ) {
467+ SootClass dummyMainClass = mainMethod .getDeclaringClass ();
468+ int idx = 0 ;
469+ String fieldName = baseName ;
470+ while (dummyMainClass .declaresFieldByName (fieldName )) {
471+ fieldName = baseName + "_" + idx ;
472+ idx ++;
473+ }
474+ SootField fld = Scene .v ().makeSootField (fieldName , type , Modifier .PRIVATE | Modifier .STATIC );
475+ mainMethod .getDeclaringClass ().addField (fld );
476+ return fld ;
477+ }
478+
409479 /**
410480 * Removes if statements that jump to the fall-through successor
411481 *
@@ -602,4 +672,8 @@ public void removeGeneratedMethods(boolean removeClass) {
602672 }
603673 }
604674
675+ public void setJavaScriptInterfaces (MultiMap <SootMethod , Stmt > javascriptInterfaceStmts ) {
676+ this .javascriptInterfaceStmts = javascriptInterfaceStmts ;
677+ }
678+
605679}
0 commit comments