1 19 20 package edu.umd.cs.findbugs.ba.npe; 21 22 import java.util.Map ; 23 import org.apache.bcel.generic.ACONST_NULL; 24 import org.apache.bcel.generic.ANEWARRAY; 25 import org.apache.bcel.generic.CHECKCAST; 26 import org.apache.bcel.generic.ConstantPoolGen; 27 import org.apache.bcel.generic.GETFIELD; 28 import org.apache.bcel.generic.GETSTATIC; 29 import org.apache.bcel.generic.INVOKEINTERFACE; 30 import org.apache.bcel.generic.INVOKESPECIAL; 31 import org.apache.bcel.generic.INVOKESTATIC; 32 import org.apache.bcel.generic.INVOKEVIRTUAL; 33 import org.apache.bcel.generic.Instruction; 34 import org.apache.bcel.generic.InvokeInstruction; 35 import org.apache.bcel.generic.LDC; 36 import org.apache.bcel.generic.LDC2_W; 37 import org.apache.bcel.generic.MULTIANEWARRAY; 38 import org.apache.bcel.generic.NEW; 39 import org.apache.bcel.generic.NEWARRAY; 40 import org.apache.bcel.generic.PUTFIELD; 41 import org.apache.bcel.generic.ReferenceType; 42 import org.apache.bcel.generic.Type; 43 44 import edu.umd.cs.findbugs.SystemProperties; 45 import edu.umd.cs.findbugs.ba.AbstractFrameModelingVisitor; 46 import edu.umd.cs.findbugs.ba.AnalysisContext; 47 import edu.umd.cs.findbugs.ba.AssertionMethods; 48 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 49 import edu.umd.cs.findbugs.ba.InstanceField; 50 import edu.umd.cs.findbugs.ba.NullnessAnnotation; 51 import edu.umd.cs.findbugs.ba.XFactory; 52 import edu.umd.cs.findbugs.ba.XField; 53 import edu.umd.cs.findbugs.ba.XMethod; 54 import edu.umd.cs.findbugs.ba.vna.AvailableLoad; 55 import edu.umd.cs.findbugs.ba.vna.ValueNumber; 56 import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow; 57 import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame; 58 59 public class IsNullValueFrameModelingVisitor extends AbstractFrameModelingVisitor<IsNullValue, IsNullValueFrame> { 60 61 private static final boolean NO_ASSERT_HACK = SystemProperties.getBoolean("inva.noAssertHack"); 62 63 private AssertionMethods assertionMethods; 64 private ValueNumberDataflow vnaDataflow; 65 private final boolean trackValueNumbers; 66 private int slotContainingNewNullValue; 67 68 public IsNullValueFrameModelingVisitor( 69 ConstantPoolGen cpg, 70 AssertionMethods assertionMethods, 71 ValueNumberDataflow vnaDataflow, 72 boolean trackValueNumbers) { 73 super(cpg); 74 this.assertionMethods = assertionMethods; 75 this.vnaDataflow = vnaDataflow; 76 this.trackValueNumbers = trackValueNumbers; 77 } 78 79 82 @Override 83 public void analyzeInstruction(Instruction ins) throws DataflowAnalysisException { 84 slotContainingNewNullValue = -1; 85 super.analyzeInstruction(ins); 86 } 87 88 92 public int getSlotContainingNewNullValue() { 93 return slotContainingNewNullValue; 94 } 95 96 @Override 97 public IsNullValue getDefaultValue() { 98 return IsNullValue.nonReportingNotNullValue(); 99 } 100 101 106 112 116 private void produce(IsNullValue value) { 117 IsNullValueFrame frame = getFrame(); 118 frame.pushValue(value); 119 newValueOnTOS(); 120 } 121 122 private void produce2(IsNullValue value) { 123 IsNullValueFrame frame = getFrame(); 124 frame.pushValue(value); 125 frame.pushValue(value); 126 } 127 128 133 private void handleInvoke(InvokeInstruction obj) { 134 Type callType = obj.getLoadClassType(getCPG()); 135 Type returnType = obj.getReturnType(getCPG()); 136 String methodName = obj.getMethodName(getCPG()); 137 138 boolean stringMethodCall = callType.equals(Type.STRING) && returnType.equals(Type.STRING); 139 140 boolean isReadLine = methodName.equals("readLine"); 141 boolean modelCallReturnValue = returnType instanceof ReferenceType; 143 144 145 if( !modelCallReturnValue) { 146 handleNormalInstruction(obj); 148 } else { 149 IsNullValue pushValue = null; 151 if (false && isReadLine) { 152 pushValue = IsNullValue.nullOnSimplePathValue().markInformationAsComingFromReturnValueOfMethod(null); 153 } else if (false && stringMethodCall) { 154 pushValue = IsNullValue.nonNullValue(); 156 } else { 157 XMethod calledMethod = XFactory.createXMethod(obj, getCPG()); 159 if (IsNullValueAnalysis.DEBUG) System.out.println("Check " + calledMethod + " for null return..."); 160 NullnessAnnotation annotation = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase().getResolvedAnnotation(calledMethod, false); 161 if (annotation == NullnessAnnotation.CHECK_FOR_NULL) { 162 if (IsNullValueAnalysis.DEBUG) { 163 System.out.println("Null value returned from " + calledMethod); 164 } 165 pushValue = IsNullValue.nullOnSimplePathValue().markInformationAsComingFromReturnValueOfMethod(calledMethod); 166 } else if (annotation == NullnessAnnotation.NONNULL) { 167 if (IsNullValueAnalysis.DEBUG) { 169 System.out.println("NonNull value return from " + calledMethod); 170 } 171 pushValue = IsNullValue.nonNullValue().markInformationAsComingFromReturnValueOfMethod(calledMethod); 172 173 } else { 174 pushValue = IsNullValue.nonReportingNotNullValue(); 175 } 176 } 177 178 modelInstruction(obj, getNumWordsConsumed(obj), getNumWordsProduced(obj), pushValue); 179 newValueOnTOS(); 180 } 181 182 if (!NO_ASSERT_HACK) { 183 if (assertionMethods.isAssertionCall(obj)) { 184 IsNullValueFrame frame = getFrame(); 185 for (int i = 0; i < frame.getNumSlots(); ++i) { 186 IsNullValue value = frame.getValue(i); 187 if (value.isDefinitelyNull() || value.isNullOnSomePath()) { 188 frame.setValue(i, IsNullValue.nonReportingNotNullValue()); 189 } 190 } 191 for(Map.Entry <ValueNumber,IsNullValue> e : frame.getKnownValueMapEntrySet()) { 192 IsNullValue value = e.getValue(); 193 if (value.isDefinitelyNull() || value.isNullOnSomePath()) 194 e.setValue(IsNullValue.nonReportingNotNullValue()); 195 196 } 197 } 198 } 199 } 200 201 205 private void newValueOnTOS() { 206 IsNullValueFrame frame= getFrame(); 207 if (frame.getStackDepth() < 1) { 208 return; 209 } 210 int tosSlot = frame.getNumSlots() - 1; 211 IsNullValue tos = frame.getValue(tosSlot); 212 if (tos.isDefinitelyNull()) { 213 slotContainingNewNullValue = tosSlot; 214 } 215 if (trackValueNumbers) { 216 try { 217 ValueNumberFrame vnaFrameAfter = vnaDataflow.getFactAfterLocation(getLocation()); 218 if (vnaFrameAfter.isValid()) { 219 ValueNumber tosVN = vnaFrameAfter.getTopValue(); 220 getFrame().setKnownValue(tosVN, tos); 221 } 222 } catch (DataflowAnalysisException e) { 223 AnalysisContext.logError("error", e); 224 } 225 } 226 } 227 228 @Override 229 public void visitPUTFIELD(PUTFIELD obj) { 230 if (getNumWordsConsumed(obj) != 2) { 231 super.visitPUTFIELD(obj); 232 return; 233 } 234 235 IsNullValue nullValueStored = null; 236 try { 237 nullValueStored = getFrame().getTopValue(); 238 } catch (DataflowAnalysisException e1) { 239 AnalysisContext.logError("Oops", e1); 240 } 241 super.visitPUTFIELD(obj); 242 InstanceField field = (InstanceField) XFactory.createXField(obj, cpg); 243 if (nullValueStored != null) 244 try { 245 ValueNumberFrame vnaFrameBefore = vnaDataflow.getFactAtLocation(getLocation()); 246 ValueNumber refValue = vnaFrameBefore.getStackValue(1); 247 AvailableLoad load = new AvailableLoad(refValue, field); 248 ValueNumberFrame vnaFrameAfter = vnaDataflow.getFactAfterLocation(getLocation()); 249 ValueNumber [] newValueNumbersForField = vnaFrameAfter.getAvailableLoad(load); 250 if (newValueNumbersForField != null && trackValueNumbers) 251 for(ValueNumber v : newValueNumbersForField) 252 getFrame().setKnownValue(v, nullValueStored); 253 } catch (DataflowAnalysisException e) { 254 AnalysisContext.logError("Oops", e); 255 } 256 } 257 258 @Override 259 public void visitGETFIELD(GETFIELD obj) { 260 if (getNumWordsProduced(obj) != 1) { 261 super.visitGETFIELD(obj); 262 return; 263 } 264 265 if (checkForKnownValue(obj)) { 266 return; 267 } 268 269 XField field = XFactory.createXField(obj, cpg); 270 271 NullnessAnnotation annotation = AnalysisContext.currentAnalysisContext().getNullnessAnnotationDatabase().getResolvedAnnotation(field, false); 272 if (annotation == NullnessAnnotation.NONNULL) { 273 modelNormalInstruction(obj, getNumWordsConsumed(obj), 0); 274 produce(IsNullValue.nonNullValue()); 275 } 276 else if (annotation == NullnessAnnotation.CHECK_FOR_NULL) { 277 modelNormalInstruction(obj, getNumWordsConsumed(obj), 0); 278 produce(IsNullValue.nullOnSimplePathValue()); 279 } else { 280 281 super.visitGETFIELD(obj); 282 } 283 284 } 285 286 289 @Override 290 public void visitGETSTATIC(GETSTATIC obj) { 291 if (getNumWordsProduced(obj) != 1) { 292 super.visitGETSTATIC(obj); 293 return; 294 } 295 296 if (checkForKnownValue(obj)) { 297 return; 298 } 299 XField field = XFactory.createXField(obj, cpg); 300 if (field.getName().startsWith("class$")) { 301 produce(IsNullValue.nonNullValue()); 302 return; 303 } 304 NullnessAnnotation annotation = AnalysisContext 305 .currentAnalysisContext().getNullnessAnnotationDatabase() 306 .getResolvedAnnotation(field, false); 307 if (annotation == NullnessAnnotation.NONNULL) { 308 modelNormalInstruction(obj, getNumWordsConsumed(obj), 0); 309 produce(IsNullValue.nonNullValue()); 310 } else if (annotation == NullnessAnnotation.CHECK_FOR_NULL) { 311 modelNormalInstruction(obj, getNumWordsConsumed(obj), 0); 312 produce(IsNullValue.nullOnSimplePathValue()); 313 } else { 314 315 super.visitGETSTATIC(obj); 316 } 317 } 318 319 330 private boolean checkForKnownValue(Instruction obj) { 331 if (trackValueNumbers) { 332 try { 333 ValueNumberFrame vnaFrameAfter = vnaDataflow.getFactAfterLocation(getLocation()); 335 if (vnaFrameAfter.isValid()) { 336 ValueNumber tosVN = vnaFrameAfter.getTopValue(); 337 IsNullValue knownValue = getFrame().getKnownValue(tosVN); 338 if (knownValue != null) { 339 modelNormalInstruction(obj, getNumWordsConsumed(obj), 0); 343 produce(knownValue); 344 return true; 345 } 346 } 347 } catch (DataflowAnalysisException e) { 348 } 350 } 351 return false; 352 } 353 354 @Override 355 public void visitACONST_NULL(ACONST_NULL obj) { 356 produce(IsNullValue.nullValue()); 357 } 358 @Override 359 public void visitNEW(NEW obj) { 360 produce(IsNullValue.nonNullValue()); 361 } 362 363 @Override 364 public void visitNEWARRAY(NEWARRAY obj) { 365 modelNormalInstruction(obj, getNumWordsConsumed(obj), 0); 366 produce(IsNullValue.nonNullValue()); 367 } 368 @Override 369 public void visitANEWARRAY(ANEWARRAY obj) { 370 modelNormalInstruction(obj, getNumWordsConsumed(obj), 0); 371 produce(IsNullValue.nonNullValue()); 372 } 373 @Override 374 public void visitMULTIANEWARRAY(MULTIANEWARRAY obj) { 375 modelNormalInstruction(obj, getNumWordsConsumed(obj), 0); 376 produce(IsNullValue.nonNullValue()); 377 } 378 @Override 379 public void visitLDC(LDC obj) { 380 produce(IsNullValue.nonNullValue()); 381 } 382 383 @Override 384 public void visitLDC2_W(LDC2_W obj) { 385 produce2(IsNullValue.nonNullValue()); 386 } 387 388 @Override 389 public void visitCHECKCAST(CHECKCAST obj) { 390 } 392 @Override 393 public void visitINVOKESTATIC(INVOKESTATIC obj) { 394 handleInvoke(obj); 395 } 396 @Override 397 public void visitINVOKESPECIAL(INVOKESPECIAL obj) { 398 handleInvoke(obj); 399 } 400 @Override 401 public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) { 402 handleInvoke(obj); 403 } 404 @Override 405 public void visitINVOKEVIRTUAL(INVOKEVIRTUAL obj) { 406 handleInvoke(obj); 407 } 408 409 } 410 411 | Popular Tags |