Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * fb-contrib - Auxiliary detectors for Java programs
   * Copyright (C) 2005-2013 Dave Brosius
   * 
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   * 
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  * 
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 package com.mebigfatguy.fbcontrib.detect;
 
 
 import  org.apache.bcel.classfile.Code;
 import  org.apache.bcel.generic.Type;
 
 
 import  edu.umd.cs.findbugs.BugInstance;
 import  edu.umd.cs.findbugs.BugReporter;
 import  edu.umd.cs.findbugs.BytecodeScanningDetector;
 import  edu.umd.cs.findbugs.OpcodeStack;
 import  edu.umd.cs.findbugs.OpcodeStack.CustomUserValue;
 import  edu.umd.cs.findbugs.ba.ClassContext;

looks for creation of arrays, that are not populated before being returned for a method. While it is possible that the method that called this method will do the work of populated the array, it seems odd that this would be the case.
 
 @CustomUserValue
 public class SuspiciousUninitializedArray extends BytecodeScanningDetector
 {
 	private static final String UNINIT_ARRAY = "Unitialized Array";
 	private final BugReporter bugReporter;
 	private OpcodeStack stack;
 	private String returnArraySig;
constructs a SUA detector given the reporter to report bugs on

Parameters:
bugReporter the sync of bug reports
 
 	public SuspiciousUninitializedArray(BugReporter bugReporter) {
 		this. = bugReporter;
 	}

overrides the visitor to reset the stack

Parameters:
classContext the context object of the currently parsed class
 
 	public void visitClassContext(ClassContext classContext) {
 		try {
 			 = new OpcodeStack();
 			super.visitClassContext(classContext);
 		} finally {
 			 = null;
 			 = null;
 		}
 	}

overrides the visitor to check to see if the method returns an array, and if so resets the stack for this method.

Parameters:
obj the context object for the currently parsed code block
 
 	public void visitCode(Code obj) {
 		String sig = getMethod().getSignature();
 		int sigPos = sig.indexOf(")[");
 		if (sigPos >= 0) {
 			.resetForMethodEntry(this);
 			 = sig.substring(sigPos + 1);
 			super.visitCode(obj);
 		}
 	}

overrides the visitor to annotate new array creation with a user value that denotes it as being uninitialized, and then if the array is populated to remove that user value. It then finds return values that have uninitialized arrays

Parameters:
seen the context parameter of the currently parsed op code
	public void sawOpcode(int seen) {
		Object userValue = null;
		try {
	        .precomputation(this);
	        
			switch (seen) {
				case NEWARRAY: {
					if (!isTOS0()) {
						int typeCode = getIntConstant();
						String sig = "[" + SignatureUtils.getTypeCodeSignature(typeCode);
						if (.equals(sig)) {
							userValue = ;
						}
					}
				}
				break;
				case ANEWARRAY: {
					if (!isTOS0()) {
						String sig = "[L" + getClassConstantOperand() + ";";
						if (.equals(sig)) {
							userValue = ;
						}
					}
				}
				break;
				case MULTIANEWARRAY: {
						userValue = ;
					}
				}
				break;
				case INVOKEVIRTUAL:
				case INVOKEINTERFACE:
				case INVOKESPECIAL:
				case INVOKESTATIC: {
					String methodSig = getSigConstantOperand();
					Type[] types = Type.getArgumentTypes(methodSig);
					for (int t = 0; t < types.length; t++) {
						Type type = types[t];
						String parmSig = type.getSignature();
						if (.equals(parmSig) || "Ljava/lang/Object;".equals(parmSig) || "[Ljava/lang/Object;".equals(parmSig)) {
							int parmIndex = types.length - t - 1;
							if (.getStackDepth() > parmIndex) {
								OpcodeStack.Item item = .getStackItem(parmIndex);
								if (item.getUserValue() != null) {
									userValue = item.getUserValue();
									int reg;
									if (userValue instanceof Integer) {
										reg = ((Integer)userValue).intValue();
else {
										reg = item.getRegisterNumber();
									}
									item.setUserValue(null);
									if (reg >= 0) {
									}
									userValue = null;
								}
							}
						}
					}
				}
				break;
				case AALOAD: {
					if (.getStackDepth() >= 2) {
						OpcodeStack.Item item = .getStackItem(1);
						if (.equals(item.getUserValue())) {
							userValue = Integer.valueOf(item.getRegisterNumber());
						}
					}
				}
				break;
				case IASTORE:
				case LASTORE:
				case FASTORE:
				case DASTORE:
				case AASTORE:
				case BASTORE:
				case CASTORE:
				case SASTORE: {
					if (.getStackDepth() >= 3) {
						OpcodeStack.Item item = .getStackItem(2);
						userValue = item.getUserValue();
						int reg;
						if (userValue instanceof Integer) {
							reg = ((Integer)userValue).intValue();
else {
							reg = item.getRegisterNumber();
						}
						item.setUserValue(null);
						if (reg >= 0) {
						}
						userValue = null;
else {
					    //error condition - stack isn't right
					}
				}
				break;
				case ASTORE:
				case ASTORE_0:
				case ASTORE_1:
				case ASTORE_2:
				case ASTORE_3: {
					int reg = RegisterUtils.getAStoreReg(thisseen);
					if (.getStackDepth() > 0) {
						OpcodeStack.Item item = .getStackItem(0);
						.set(reg, (.equals(item.getUserValue())));
else {
					}
				}
				break;
				case ALOAD:
				case ALOAD_0:
				case ALOAD_1:
				case ALOAD_2:
				case ALOAD_3: {
					int reg = RegisterUtils.getALoadReg(thisseen);
					if (.get(reg)) {
						userValue = ;
					}
				}
				break;
				case PUTFIELD: {
					if (.getStackDepth() > 0) {
						OpcodeStack.Item item = .getStackItem(0);
						item.setUserValue(null);
						int reg = item.getRegisterNumber();
						if (reg >= 0) {
						}
					}
				}
				break;
				case ARETURN: {
					if (.getStackDepth() > 0) {
						OpcodeStack.Item item = .getStackItem(0);
						if (.equals(item.getUserValue()))
							.reportBug(new BugInstance(this"SUA_SUSPICIOUS_UNINITIALIZED_ARRAY", NORMAL_PRIORITY)
							           .addClass(this)
							           .addMethod(this)
							           .addSourceLine(this));
					}					
				}
				break;
			}
finally {
			TernaryPatcher.pre(seen);
			.sawOpcode(thisseen);
			TernaryPatcher.post(seen);
			if (.getStackDepth() > 0) {
				OpcodeStack.Item item = .getStackItem(0);
				item.setUserValue(userValue);
			}
		}
	}
	private boolean isTOS0() {
		if (.getStackDepth() > 0) {
			OpcodeStack.Item item = .getStackItem(0);
			return item.mustBeZero();
		}
		return false;
	}
New to GrepCode? Check out our FAQ X