pascal.taie.analysis.pta.plugin.assertion.AssertionChecker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tai-e Show documentation
Show all versions of tai-e Show documentation
An easy-to-learn/use static analysis framework for Java
The newest version!
/*
* Tai-e: A Static Analysis Framework for Java
*
* Copyright (C) 2022 Tian Tan
* Copyright (C) 2022 Yue Li
*
* This file is part of Tai-e.
*
* Tai-e 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 3
* of the License, or (at your option) any later version.
*
* Tai-e 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 Tai-e. If not, see .
*/
package pascal.taie.analysis.pta.plugin.assertion;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import pascal.taie.analysis.pta.PointerAnalysisResult;
import pascal.taie.analysis.pta.core.solver.Solver;
import pascal.taie.analysis.pta.plugin.Plugin;
import pascal.taie.ir.stmt.Invoke;
import pascal.taie.language.classes.ClassHierarchy;
import pascal.taie.language.classes.JClass;
import pascal.taie.language.classes.JMethod;
import pascal.taie.language.type.TypeSystem;
import pascal.taie.util.collection.Maps;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Implements a mechanism for checking pointer analysis assertions.
* This mechanism is used for testing pointer analysis.
*/
public class AssertionChecker implements Plugin {
private static final Logger logger = LogManager.getLogger(AssertionChecker.class);
/**
* Name of the stub class that provides assertion APIs.
*/
static final String PTA_ASSERT = "PTAAssert";
private Solver solver;
private JClass ptaAssert;
@Override
public void setSolver(Solver solver) {
this.solver = solver;
this.ptaAssert = solver.getHierarchy().getClass(PTA_ASSERT);
}
@Override
public void onStart() {
if (ptaAssert != null) {
ptaAssert.getDeclaredMethods().forEach(solver::addIgnoredMethod);
}
}
@Override
public void onFinish() {
if (ptaAssert == null) {
logger.warn("class '{}' is not loaded, failed to enable {}",
PTA_ASSERT, AssertionChecker.class.getSimpleName());
return;
}
Map checkers = getCheckers(solver.getHierarchy());
List failures = checkAssertions(solver, checkers);
processFailures(failures);
}
private static Map getCheckers(ClassHierarchy hierarchy) {
Map checkers = Maps.newLinkedHashMap();
for (var value : Checkers.values()) {
JMethod assertApi = hierarchy.getMethod(value.getApi());
checkers.put(assertApi, value.getChecker());
}
return checkers;
}
private static List checkAssertions(Solver solver, Map checkers) {
PointerAnalysisResult pta = solver.getResult();
ClassHierarchy hierarchy = solver.getHierarchy();
TypeSystem typeSystem = solver.getTypeSystem();
List failures = new ArrayList<>();
for (JMethod assertApi : checkers.keySet()) {
for (Invoke invoke : pta.getCallGraph().getCallersOf(assertApi)) {
Checker checker = checkers.get(assertApi);
Result result = checker.check(invoke, pta, hierarchy, typeSystem);
if (!result.failures().isEmpty()) {
failures.add(result);
}
}
}
return failures;
}
private static void processFailures(List failures) {
if (!failures.isEmpty()) {
StringBuilder msg = new StringBuilder("Pointer analysis assertion failures:\n");
failures.forEach(result -> {
msg.append(result.invoke()).append('\n');
msg.append(" assertion: ").append(result.assertion()).append('\n');
msg.append(" failures:\n");
result.failures().forEach((elem, givenResult) ->
msg.append(String.format(" %s -> %s\n", elem, givenResult)));
});
throw new AssertionError(msg);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy