1 19 20 package soot.jimple.toolkits.annotation.qualifiers; 21 22 import soot.*; 23 import java.util.*; 24 import soot.toolkits.graph.*; 25 import soot.toolkits.scalar.*; 26 import soot.tagkit.*; 27 import soot.jimple.*; 28 import soot.util.queue.*; 29 import soot.jimple.toolkits.callgraph.*; 30 31 34 public class TightestQualifiersTagger extends SceneTransformer { 35 36 public TightestQualifiersTagger(Singletons.Global g) {} 37 public static TightestQualifiersTagger v() { return G.v().soot_jimple_toolkits_annotation_qualifiers_TightestQualifiersTagger();} 38 39 public final static int RESULT_PUBLIC = 0; 40 public final static int RESULT_PACKAGE = 1; 41 public final static int RESULT_PROTECTED = 2; 42 public final static int RESULT_PRIVATE = 3; 43 44 private HashMap methodResultsMap = new HashMap(); 45 private HashMap fieldResultsMap = new HashMap(); 46 private MethodToContexts methodToContexts; 47 48 protected void internalTransform(String phaseName, Map options){ 49 50 handleMethods(); 51 handleFields(); 52 } 53 54 private void handleMethods() { 55 Iterator classesIt = Scene.v().getApplicationClasses().iterator(); 56 while (classesIt.hasNext()){ 57 SootClass appClass = (SootClass)classesIt.next(); 58 Iterator methsIt = appClass.getMethods().iterator(); 59 while (methsIt.hasNext()){ 60 SootMethod sm = (SootMethod)methsIt.next(); 61 if (!Scene.v().getReachableMethods().contains(sm)) continue; 63 analyzeMethod(sm); 64 } 65 } 66 67 Iterator methStatIt = methodResultsMap.keySet().iterator(); 68 while (methStatIt.hasNext()) { 69 SootMethod meth = (SootMethod)methStatIt.next(); 70 int result = ((Integer )methodResultsMap.get(meth)).intValue(); 71 String sRes = "Public"; 72 if (result == RESULT_PUBLIC){ 73 sRes = "Public"; 74 } 75 else if (result == RESULT_PROTECTED){ 76 sRes = "Protected"; 77 } 78 else if (result == RESULT_PACKAGE){ 79 sRes = "Package"; 80 } 81 else if (result == RESULT_PRIVATE){ 82 sRes = "Private"; 83 } 84 85 String actual = null; 86 if (Modifier.isPublic(meth.getModifiers())){ 87 actual = "Public"; 88 } 89 else if (Modifier.isProtected(meth.getModifiers())){ 90 actual = "Protected"; 91 } 92 else if (Modifier.isPrivate(meth.getModifiers())){ 93 actual = "Private"; 94 } 95 else { 96 actual = "Package"; 97 } 98 99 101 if (!sRes.equals(actual)) { 102 if (meth.getName().equals("<init>")){ 103 meth.addTag(new StringTag("Constructor: "+meth.getDeclaringClass().getName()+" has "+actual+" level access, can have: "+sRes+" level access.", "Tightest Qualifiers")); 104 } 105 else { 106 meth.addTag(new StringTag("Method: "+meth.getName()+" has "+actual+" level access, can have: "+sRes+" level access.", "Tightest Qualifiers")); 107 } 108 meth.addTag(new ColorTag(255, 10, 0, true, "Tightest Qualifiers")); 109 } 110 } 111 } 112 113 114 private void analyzeMethod(SootMethod sm){ 115 116 CallGraph cg = Scene.v().getCallGraph(); 117 118 123 if( methodToContexts == null ) { 124 methodToContexts = new MethodToContexts( Scene.v().getReachableMethods().listener() ); 125 } 126 127 for( Iterator momcIt = methodToContexts.get(sm).iterator(); momcIt.hasNext(); ) { 128 final MethodOrMethodContext momc = (MethodOrMethodContext) momcIt.next(); 129 Iterator callerEdges = cg.edgesInto(momc); 130 while (callerEdges.hasNext()){ 131 Edge callEdge = (Edge)callerEdges.next(); 132 if (!callEdge.isExplicit()) continue; 133 SootMethod methodCaller = callEdge.src(); 134 SootClass callingClass = methodCaller.getDeclaringClass(); 136 if (Modifier.isPublic(sm.getModifiers())){ 138 analyzePublicMethod(sm, callingClass); 139 } 140 else if (Modifier.isProtected(sm.getModifiers())){ 142 analyzeProtectedMethod(sm, callingClass); 143 } 144 else if (Modifier.isPrivate(sm.getModifiers())){ 146 } 147 else { 149 analyzePackageMethod(sm, callingClass); 150 } 151 152 } 153 } 154 155 } 156 157 private boolean analyzeProtectedMethod(SootMethod sm, SootClass callingClass){ 158 SootClass methodClass = sm.getDeclaringClass(); 159 160 162 boolean insidePackageAccess = isCallSamePackage(callingClass, methodClass); 163 boolean subClassAccess = isCallClassSubClass(callingClass, methodClass); 164 boolean sameClassAccess = isCallClassMethodClass(callingClass, methodClass); 165 166 if (!insidePackageAccess && subClassAccess) { 167 methodResultsMap.put(sm, new Integer (RESULT_PROTECTED)); 168 return true; 169 } 170 else if (insidePackageAccess && !sameClassAccess) { 171 updateToPackage(sm); 172 return false; 173 } 174 else { 175 updateToPrivate(sm); 176 return false; 177 } 178 } 179 180 private boolean analyzePackageMethod(SootMethod sm, SootClass callingClass){ 181 SootClass methodClass = sm.getDeclaringClass(); 182 183 boolean insidePackageAccess = isCallSamePackage(callingClass, methodClass); 185 boolean subClassAccess = isCallClassSubClass(callingClass, methodClass); 186 boolean sameClassAccess = isCallClassMethodClass(callingClass, methodClass); 187 188 if (insidePackageAccess && !sameClassAccess) { 189 updateToPackage(sm); 190 return true; 191 } 192 else { 193 updateToPrivate(sm); 194 return false; 195 } 196 } 197 198 private boolean analyzePublicMethod(SootMethod sm, SootClass callingClass){ 199 200 SootClass methodClass = sm.getDeclaringClass(); 201 202 204 boolean insidePackageAccess = isCallSamePackage(callingClass, methodClass); 205 boolean subClassAccess = isCallClassSubClass(callingClass, methodClass); 206 boolean sameClassAccess = isCallClassMethodClass(callingClass, methodClass); 207 208 if (!insidePackageAccess && !subClassAccess){ 209 methodResultsMap.put(sm, new Integer (RESULT_PUBLIC)); 210 return true; 211 } 212 else if (!insidePackageAccess && subClassAccess) { 213 updateToProtected(sm); 214 return false; 215 } 216 else if (insidePackageAccess && !sameClassAccess) { 217 updateToPackage(sm); 218 return false; 219 } 220 else { 221 updateToPrivate(sm); 222 return false; 223 } 224 225 } 226 227 private void updateToProtected(SootMethod sm){ 228 if (!methodResultsMap.containsKey(sm)){ 229 methodResultsMap.put(sm, new Integer (RESULT_PROTECTED)); 230 } 231 else { 232 if (((Integer )methodResultsMap.get(sm)).intValue() != RESULT_PUBLIC){ 233 methodResultsMap.put(sm, new Integer (RESULT_PROTECTED)); 234 } 235 } 236 } 237 238 private void updateToPackage(SootMethod sm){ 239 if (!methodResultsMap.containsKey(sm)){ 240 methodResultsMap.put(sm, new Integer (RESULT_PACKAGE)); 241 } 242 else { 243 if (((Integer )methodResultsMap.get(sm)).intValue() == RESULT_PRIVATE){ 244 methodResultsMap.put(sm, new Integer (RESULT_PACKAGE)); 245 } 246 } 247 } 248 249 private void updateToPrivate(SootMethod sm){ 250 if (!methodResultsMap.containsKey(sm)) { 251 methodResultsMap.put(sm, new Integer (RESULT_PRIVATE)); 252 } 253 } 254 255 private boolean isCallClassMethodClass(SootClass call, SootClass check){ 256 if (call.equals(check)) return true; 257 return false; 258 } 259 260 private boolean isCallClassSubClass(SootClass call, SootClass check){ 261 if (!call.hasSuperclass()) return false; 262 if (call.getSuperclass().equals(check)) return true; 263 return false; 264 } 265 266 private boolean isCallSamePackage(SootClass call, SootClass check){ 267 if (call.getPackageName().equals(check.getPackageName())) return true; 268 return false; 269 } 270 271 private void handleFields(){ 272 Iterator classesIt = Scene.v().getApplicationClasses().iterator(); 273 while (classesIt.hasNext()){ 274 SootClass appClass = (SootClass)classesIt.next(); 275 Iterator fieldsIt = appClass.getFields().iterator(); 276 while (fieldsIt.hasNext()){ 277 SootField sf = (SootField)fieldsIt.next(); 278 analyzeField(sf); 279 } 280 } 281 282 Iterator fieldStatIt = fieldResultsMap.keySet().iterator(); 283 while (fieldStatIt.hasNext()) { 284 SootField f = (SootField)fieldStatIt.next(); 285 int result = ((Integer )fieldResultsMap.get(f)).intValue(); 286 String sRes = "Public"; 287 if (result == RESULT_PUBLIC){ 288 sRes = "Public"; 289 } 290 else if (result == RESULT_PROTECTED){ 291 sRes = "Protected"; 292 } 293 else if (result == RESULT_PACKAGE){ 294 sRes = "Package"; 295 } 296 else if (result == RESULT_PRIVATE){ 297 sRes = "Private"; 298 } 299 300 String actual = null; 301 if (Modifier.isPublic(f.getModifiers())){ 302 actual = "Public"; 304 } 305 else if (Modifier.isProtected(f.getModifiers())){ 306 actual = "Protected"; 307 } 308 else if (Modifier.isPrivate(f.getModifiers())){ 309 actual = "Private"; 310 } 311 else { 312 actual = "Package"; 313 } 314 315 317 if (!sRes.equals(actual)){ 318 f.addTag(new StringTag("Field: "+f.getName()+" has "+actual+" level access, can have: "+sRes+" level access.", "Tightest Qualifiers")); 319 f.addTag(new ColorTag(255, 10, 0, true, "Tightest Qualifiers")); 320 } 321 } 322 } 323 324 private void analyzeField(SootField sf){ 325 326 Iterator classesIt = Scene.v().getApplicationClasses().iterator(); 328 while (classesIt.hasNext()) { 329 SootClass appClass = (SootClass)classesIt.next(); 330 Iterator mIt = appClass.getMethods().iterator(); 331 while (mIt.hasNext()) { 332 SootMethod sm = (SootMethod)mIt.next(); 333 if (!sm.hasActiveBody()) continue; 334 if (!Scene.v().getReachableMethods().contains(sm)) continue; 335 Body b = sm.getActiveBody(); 336 337 Iterator usesIt = b.getUseBoxes().iterator(); 338 while (usesIt.hasNext()) { 339 ValueBox vBox = (ValueBox)usesIt.next(); 340 Value v = vBox.getValue(); 341 if (v instanceof FieldRef) { 342 FieldRef fieldRef = (FieldRef)v; 343 SootField f = fieldRef.getField(); 344 if (f.equals(sf)) { 345 if (Modifier.isPublic(sf.getModifiers())) { 346 if (analyzePublicField(sf, appClass)) return; 347 } 348 else if (Modifier.isProtected(sf.getModifiers())) { 349 analyzeProtectedField(sf, appClass); 350 } 351 else if(Modifier.isPrivate(sf.getModifiers())) { 352 } 353 else { 354 analyzePackageField(sf, appClass); 355 } 356 } 357 } 358 } 359 } 360 } 361 } 362 363 private boolean analyzePublicField(SootField sf, SootClass callingClass){ 364 SootClass fieldClass = sf.getDeclaringClass(); 365 366 367 boolean insidePackageAccess = isCallSamePackage(callingClass, fieldClass); 368 boolean subClassAccess = isCallClassSubClass(callingClass, fieldClass); 369 boolean sameClassAccess = isCallClassMethodClass(callingClass, fieldClass); 370 371 if (!insidePackageAccess && !subClassAccess){ 372 fieldResultsMap.put(sf, new Integer (RESULT_PUBLIC)); 373 return true; 374 } 375 else if (!insidePackageAccess && subClassAccess) { 376 updateToProtected(sf); 377 return false; 378 } 379 else if (insidePackageAccess && !sameClassAccess) { 380 updateToPackage(sf); 381 return false; 382 } 383 else { 384 updateToPrivate(sf); 385 return false; 386 } 387 388 } 389 390 private boolean analyzeProtectedField(SootField sf, SootClass callingClass){ 391 SootClass fieldClass = sf.getDeclaringClass(); 392 393 boolean insidePackageAccess = isCallSamePackage(callingClass, fieldClass); 394 boolean subClassAccess = isCallClassSubClass(callingClass, fieldClass); 395 boolean sameClassAccess = isCallClassMethodClass(callingClass, fieldClass); 396 397 if (!insidePackageAccess && subClassAccess) { 398 fieldResultsMap.put(sf, new Integer (RESULT_PROTECTED)); 399 return true; 400 } 401 else if (insidePackageAccess && !sameClassAccess) { 402 updateToPackage(sf); 403 return false; 404 } 405 else { 406 updateToPrivate(sf); 407 return false; 408 } 409 } 410 411 private boolean analyzePackageField(SootField sf, SootClass callingClass){ 412 SootClass fieldClass = sf.getDeclaringClass(); 413 414 boolean insidePackageAccess = isCallSamePackage(callingClass, fieldClass); 415 boolean subClassAccess = isCallClassSubClass(callingClass, fieldClass); 416 boolean sameClassAccess = isCallClassMethodClass(callingClass, fieldClass); 417 418 if (insidePackageAccess && !sameClassAccess) { 419 updateToPackage(sf); 420 return true; 421 } 422 else { 423 updateToPrivate(sf); 424 return false; 425 } 426 } 427 428 private void updateToProtected(SootField sf){ 429 if (!fieldResultsMap.containsKey(sf)){ 430 fieldResultsMap.put(sf, new Integer (RESULT_PROTECTED)); 431 } 432 else { 433 if (((Integer )fieldResultsMap.get(sf)).intValue() != RESULT_PUBLIC){ 434 fieldResultsMap.put(sf, new Integer (RESULT_PROTECTED)); 435 } 436 } 437 } 438 439 private void updateToPackage(SootField sf){ 440 if (!fieldResultsMap.containsKey(sf)){ 441 fieldResultsMap.put(sf, new Integer (RESULT_PACKAGE)); 442 } 443 else { 444 if (((Integer )fieldResultsMap.get(sf)).intValue() == RESULT_PRIVATE){ 445 fieldResultsMap.put(sf, new Integer (RESULT_PACKAGE)); 446 } 447 } 448 } 449 450 private void updateToPrivate(SootField sf){ 451 if (!fieldResultsMap.containsKey(sf)) { 452 fieldResultsMap.put(sf, new Integer (RESULT_PRIVATE)); 453 } 454 } 455 } 456 | Popular Tags |