//
// Copyright (C) 2012 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.listener;
import cmu.conditional.One;
import de.fosd.typechef.featureexpr.FeatureExprFactory;
import gov.nasa.jpf.Config;
import gov.nasa.jpf.JPF;
import gov.nasa.jpf.ListenerAdapter;
import gov.nasa.jpf.util.JPFLogger;
import gov.nasa.jpf.vm.Instruction;
import gov.nasa.jpf.vm.MethodInfo;
import gov.nasa.jpf.vm.StackFrame;
import gov.nasa.jpf.vm.ThreadInfo;
import gov.nasa.jpf.vm.VM;
/**
* listener that throws a java.lang.StackOverflowError in case a thread
* exceeds a configured max stack depth
*
* <2do> - maybe we should only count visible stackframes, i.e. the ones for
* which we have invoke insns on the stack
*/
public class StackDepthChecker extends ListenerAdapter {
static JPFLogger log = JPF.getLogger("gov.nasa.jpf.listener.StackDepthChecker");
protected int maxDepth;
public StackDepthChecker (Config config, JPF jpf){
maxDepth = config.getInt( "sdc.max_stack_depth", 42);
}
@Override
public void methodEntered (VM vm, ThreadInfo thread, MethodInfo mi){
ThreadInfo ti = ThreadInfo.getCurrentThread();
int depth = ti.getStackDepth(); // note this is only an approximation since it also returns natives and overlays
if (depth > maxDepth){
log.info("configured vm.max_stack_depth exceeded: ", depth);
// NOTE - we get this notification from inside of the InvokeInstruction.enter(),
// i.e. before we get the instructionExecuted(). Throwing exceptions is
// therefore a bit harder since we have to set the next pc explicitly
Instruction nextPc = ti.createAndThrowException(FeatureExprFactory.True(), "java.lang.StackOverflowError");
StackFrame topFrame = ti.getModifiableTopFrame();
topFrame.setPC(new One<>(nextPc));
}
}
}