All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.infoflow.data.pathBuilders.BatchPathBuilder Maven / Gradle / Ivy

The newest version!
package soot.jimple.infoflow.data.pathBuilders;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import soot.jimple.infoflow.InfoflowManager;
import soot.jimple.infoflow.data.AbstractionAtSink;
import soot.jimple.infoflow.memory.ISolverTerminationReason;
import soot.jimple.infoflow.results.InfoflowResults;
import soot.jimple.infoflow.solver.executors.InterruptableExecutor;

/**
 * Path builder that forwards all its requests to another path builder in
 * batches. This builder waits for each batch to complete before submitting
 * another batch. Use this path builder to reduce the memory consumption of the
 * path building process by keeping less paths in memory at the same time.
 *
 * @author Steven Arzt
 */
public class BatchPathBuilder extends AbstractAbstractionPathBuilder {

	protected final IAbstractionPathBuilder innerBuilder;
	protected int batchSize = 5;
	protected ISolverTerminationReason terminationReason = null;

	public BatchPathBuilder(InfoflowManager manager, IAbstractionPathBuilder innerBuilder) {
		super(manager);
		this.innerBuilder = innerBuilder;
	}

	@Override
	public void computeTaintPaths(Set res) {
		Set batch = new HashSet<>();
		Iterator resIt = res.iterator();
		int batchId = 1;
		long startTime = System.nanoTime();
		long totalTime = manager.getConfig().getPathConfiguration().getPathReconstructionTotalTime();

		while (resIt.hasNext()) {
			// checking if the execution time exceeds the configured totalTime and logging
			long executionNanoTime = System.nanoTime() - startTime;
			if (totalTime > 0 && executionNanoTime / 1E9 >= totalTime) {
				logger.info(
						"Path Reconstruction has terminated as it exceeds the configured pathReconstructionTotalTime.");
				logger.info("The pathReconstructionTotalTime is set to " + totalTime + "seconds.");
				logger.info("Now the current batchId:" + batchId);
				logger.info("The number of remaining res:" + (res.size() - batchId * batch.size()));
				break;
			} else {
				logger.info("Path Reconstruction has used " + executionNanoTime / 1E9 + " seconds");
			}

			// Build the next batch
			while (batch.size() < this.batchSize && resIt.hasNext())
				batch.add(resIt.next());
			logger.info("Running path reconstruction batch {} with {} elements", batchId++, batch.size());

			// Run the next batch
			long beforeBatch = System.nanoTime();
			innerBuilder.reset();
			innerBuilder.computeTaintPaths(batch);

			// Save the termination reason
			if (this.terminationReason == null)
				this.terminationReason = innerBuilder.getTerminationReason();
			else
				this.terminationReason = this.terminationReason.combine(innerBuilder.getTerminationReason());

			// Wait for the batch to complete
			if (innerBuilder instanceof ConcurrentAbstractionPathBuilder) {
				ConcurrentAbstractionPathBuilder concurrentBuilder = (ConcurrentAbstractionPathBuilder) innerBuilder;
				final InterruptableExecutor resultExecutor = concurrentBuilder.getExecutor();
				try {
					// The path reconstruction should stop on time anyway. In case it doesn't, we
					// make sure that we don't get stuck.
					long pathTimeout = manager.getConfig().getPathConfiguration().getPathReconstructionTimeout();
					if (pathTimeout > 0)
						resultExecutor.awaitCompletion(pathTimeout + 20, TimeUnit.SECONDS);
					else
						resultExecutor.awaitCompletion();
				} catch (InterruptedException e) {
					logger.error("Could not wait for executor termination", e);
				}
				resultExecutor.reset();
			}
			logger.info("Single batch has used " + (System.nanoTime() - beforeBatch) / 1E9 + " seconds");

			// Prepare for the next batch
			batch.clear();
		}
	}

	@Override
	public InfoflowResults getResults() {
		return innerBuilder.getResults();
	}

	@Override
	public void runIncrementalPathComputation() {
		innerBuilder.runIncrementalPathComputation();
	}

	@Override
	public void forceTerminate(ISolverTerminationReason reason) {
		innerBuilder.forceTerminate(reason);
	}

	@Override
	public boolean isTerminated() {
		return innerBuilder.isTerminated();
	}

	@Override
	public boolean isKilled() {
		return innerBuilder.isKilled();
	}

	@Override
	public ISolverTerminationReason getTerminationReason() {
		return terminationReason;
	}

	@Override
	public void reset() {
		innerBuilder.reset();
	}

	@Override
	public void addStatusListener(IMemoryBoundedSolverStatusNotification listener) {
		innerBuilder.addStatusListener(listener);
	}

	/**
	 * Sets the number of paths that shall be part of one batch, i.e., that shall be
	 * forwarded to the inner path builder at the same time
	 *
	 * @param batchSize The number of paths in one batch
	 */
	public void setBatchSize(int batchSize) {
		this.batchSize = batchSize;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy