Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===- Assignment-3-Helper.h -- Abstract Interpretation Helper funcs --//
//===- AEReporter.h -- Abstract Interpretation bug reporter --//
//
// SVF: Static Value-Flow Analysis
//
Expand All @@ -19,11 +19,9 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
//===----------------------------------------------------------------------===//
/*
* Abstract Interpretation Helper Functions
*
* Created on: Feb 19, 2024
*/

#ifndef ASSIGNMENT_3_AE_REPORTER_H
#define ASSIGNMENT_3_AE_REPORTER_H

#include "AE/Core/AbstractState.h"
#include "AE/Svfexe/AEDetector.h"
Expand All @@ -34,44 +32,11 @@
#include <ostream>
#include <string>
#include <vector>
namespace SVF {
class AbstractInterpretation;

/// Narrow facade over the SVF abstract-interpretation state manager.
///
/// Students interact with the abstract state *only* through this object
/// (the `svfStateMgr` member of AbstractExecution). It forwards exactly the
/// state read/write and GEP primitives the assignment is allowed to use, and
/// deliberately exposes no path to the SVF external-API modeller
/// (AbsExtAPI / handleExtAPI / getRangeLimitFromType / getUtils), so the
/// memory/string library summaries and the cast-range logic must be written
/// by hand. Method bodies live in Assignment_3_Helper.cpp.
class Ass3StateManager {
public:
explicit Ass3StateManager(AbstractInterpretation* ai = nullptr) : ai(ai) {}

const AbstractValue& getAbsValue(const ValVar* var, const ICFGNode* node);
const AbstractValue& getAbsValue(const ObjVar* var, const ICFGNode* node);
const AbstractValue& getAbsValue(const SVFVar* var, const ICFGNode* node);

void updateAbsValue(const ValVar* var, const AbstractValue& val, const ICFGNode* node);
void updateAbsValue(const ObjVar* var, const AbstractValue& val, const ICFGNode* node);
void updateAbsValue(const SVFVar* var, const AbstractValue& val, const ICFGNode* node);

AbstractValue loadValue(const ValVar* pointer, const ICFGNode* node);
void storeValue(const ValVar* pointer, const AbstractValue& val, const ICFGNode* node);

AddressValue getGepObjAddrs(const ValVar* pointer, IntervalValue offset);
IntervalValue getGepElementIndex(const GepStmt* gep);
IntervalValue getGepByteOffset(const GepStmt* gep);
u32_t getAllocaInstByteSize(const AddrStmt* addr);
namespace SVF {

private:
// harness-only: AbstractExecution reaches the underlying manager for the
// post-trace; never exposed to student code.
friend class AbstractExecution;
AbstractInterpretation* ai;
};
class ICFG;
class CallICFGNode;

struct AssignmentCaseConfig {
std::string caseId;
Expand All @@ -89,8 +54,39 @@ namespace SVF {

std::string ass3JsonEscape(const std::string& input);

class AbstractExecutionHelper {
/// Bug reporter and harness bookkeeper for the Assignment-3
/// abstract-interpretation pipeline. Owns the bug list plus the
/// harness-only state (analysed ICFG nodes, validated assertion
/// call sites, case config) and renders the human / JSON summary
/// consumed by the grader.
class AEReporter {
public:
AEReporter() = default;
explicit AEReporter(const AssignmentCaseConfig& config) : caseConfig(config) {}

const AssignmentCaseConfig& getCaseConfig() const { return caseConfig; }
void setCaseConfig(const AssignmentCaseConfig& config) { caseConfig = config; }

/// Coverage tracking: harness records every ICFG node it processed.
void noteAnalyzed(const ICFGNode* node) { analyzedNodes.insert(node); }
u32_t getAnalyzedNodeCount() const {
return static_cast<u32_t>(analyzedNodes.size());
}
u32_t getTotalNodeCount(const ICFG* icfg) const;
double getICFGCoverage(const ICFG* icfg) const;

/// Assertion-point tracking: harness records every stub call site it
/// actually reached so `ensureAllAssertsValidated` can detect missed
/// ones.
void noteAssertionPoint(const CallICFGNode* call) { assert_points.insert(call); }
bool isAssertionPoint(const CallICFGNode* call) const {
return assert_points.find(call) != assert_points.end();
}

bool hasTargetReport() const;
void writeJsonSummary(std::ostream& os, const ICFG* icfg,
double wallSeconds, int exitCode,
bool assertsValidated) const;

/// Add a detected bug to the bug reporter and print the report
///@{
Expand Down Expand Up @@ -155,5 +151,14 @@ namespace SVF {
SVFBugReport _recoder;
Map<const ICFGNode*, std::string> _nodeToBugInfo;
std::vector<AssignmentBugReport> _reports;

/// Harness bookkeeping (moved here from AbstractExecution so
/// Assignment_3.h stays focused on student-facing surface).
AssignmentCaseConfig caseConfig;
Set<const ICFGNode*> analyzedNodes;
Set<const CallICFGNode*> assert_points;
};
}

} // namespace SVF

#endif // ASSIGNMENT_3_AE_REPORTER_H
10 changes: 6 additions & 4 deletions Assignment-3/CPP/Assignment_3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
//
//===----------------------------------------------------------------------===//
/*
* Abstract Interpretation and buffer overflow detection
* Abstract Interpretation and bug detection
*
* Created on: Feb 19, 2024
*/
Expand All @@ -33,9 +33,11 @@ using namespace SVFUtil;
// ===========================================================================
// Student TODOs
// ===========================================================================
// Implement abstract interpretation for the assignment cases. The harness
// (Assignment_3_Helper.cpp) drives the analysis and only calls into the six
// entry points below; design and add any internal helpers you need.
// Implement abstract interpretation for verification and bug detection. The
// harness (AEReporter.cpp) drives the analysis and calls into the six entry
// points below (please do not delete); You are free to add any internal
// classes and helper methods you need within Assignment_3.h and
// Assignment_3.cpp.
// ===========================================================================

void AbstractExecution::updateAbsState(const SVFStmt* stmt) {
Expand Down
68 changes: 34 additions & 34 deletions Assignment-3/CPP/Assignment_3.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,29 @@
//
//===----------------------------------------------------------------------===//
/*
* Abstract Interpretation and buffer overflow detection
* Abstract Interpretation and bug detection
*
* Created on: Feb 19, 2024
*/
#include "Assignment_3_Helper.h"
#include "AEReporter.h"
#include "SVFIR/SVFIR.h"
#include <ostream>

namespace SVF {
class AbstractInterpretation;
class AndersenWaveDiff;
/// Abstract Execution class
class AbstractExecution {
public:
/// Constructor
explicit AbstractExecution(const AssignmentCaseConfig& config = AssignmentCaseConfig())
: caseConfig(config) {
: bugReporter(config) {
}

/// Harness reporter accessor (used by test-ae.cpp for JSON summary).
AEReporter& getReporter() { return bugReporter; }
const AEReporter& getReporter() const { return bugReporter; }

virtual void runOnModule(ICFG* icfg);

static AbstractExecution& getAEInstance()
Expand Down Expand Up @@ -68,6 +73,27 @@ namespace SVF {
/// External-API value summaries (student TODO).
void updateStateOnExtCall(const SVF::CallICFGNode* extCallNode);

/// State-manager primitives (forward to the underlying
/// AbstractInterpretation). Use these from the statement transfer
/// functions and the external-API summaries.
///@{
const AbstractValue& getAbsValue(const ValVar* var, const ICFGNode* node);
const AbstractValue& getAbsValue(const ObjVar* var, const ICFGNode* node);
const AbstractValue& getAbsValue(const SVFVar* var, const ICFGNode* node);

void updateAbsValue(const ValVar* var, const AbstractValue& val, const ICFGNode* node);
void updateAbsValue(const ObjVar* var, const AbstractValue& val, const ICFGNode* node);
void updateAbsValue(const SVFVar* var, const AbstractValue& val, const ICFGNode* node);

AbstractValue loadValue(const ValVar* pointer, const ICFGNode* node);
void storeValue(const ValVar* pointer, const AbstractValue& val, const ICFGNode* node);

AddressValue getGepObjAddrs(const ValVar* pointer, IntervalValue offset);
IntervalValue getGepElementIndex(const GepStmt* gep);
IntervalValue getGepByteOffset(const GepStmt* gep);
u32_t getAllocaInstByteSize(const AddrStmt* addr);
///@}

/// Handle stub functions for verifying abstract interpretation results
void handleStubFunctions(const CallICFGNode* call);

Expand Down Expand Up @@ -95,58 +121,32 @@ namespace SVF {

void ensureAllAssertsValidated();

/// Case-based grading/reporting helpers. These are intentionally
/// end-to-end: the grader should score TP/FP/time/coverage per case,
/// while module tags are only diagnosis hints.
void writeJsonSummary(std::ostream& os, double wallSeconds, int exitCode,
bool assertsValidated) const;
u32_t getAnalyzedNodeCount() const;
u32_t getTotalNodeCount() const;
double getICFGCoverage() const;
bool hasTargetReport() const;
const AssignmentCaseConfig& getCaseConfig() const {
return caseConfig;
}

/// Destructor
virtual ~AbstractExecution() {
// svfStateMgr is the AbstractInterpretation singleton; SVF owns its lifetime.
// `ai` is the AbstractInterpretation singleton; SVF owns its lifetime.
}

protected:
/// SVFIR and ICFG
SVFIR* svfir;
ICFG* icfg;
/// Narrow state-manager facade used by all student code: it forwards only
/// the whitelisted state read/write and GEP primitives and exposes no
/// path to the SVF external-API modeller (see Ass3StateManager).
Ass3StateManager* svfStateMgr = nullptr;

/// Andersen pointer analysis (owns the call graph + SCC used to drive
/// the interprocedural WTO); created in initWTO().
AndersenWaveDiff* ander = nullptr;
/// Map a function to its corresponding WTO
Map<const FunObjVar*, ICFGWTO*> funcToWTO;
/// Functions whose WTO is currently being iterated; re-entry returns
/// early so the outer cycle drives the recursion to a fixpoint.
Set<const FunObjVar*> _funcsInFlight;
/// Abstract trace immediately before an ICFGNode.
Map<const ICFGNode*, AbstractState> preAbsTrace;
/// The "post" trace lives inside the manager (defined in the helper).
Map<const ICFGNode*, AbstractState>& postAbsTrace();

private:
AssignmentCaseConfig caseConfig;

AbstractExecutionHelper bugReporter;

Set<const CallICFGNode*> assert_points;
Set<const ICFGNode*> analyzedNodes;

Map<const ICFGNode*, const ICFGCycleWTO*> cycleHeadToCycle;
AEReporter bugReporter;

/// harness-only raw handle to the underlying state manager; never used by
/// student code (which only sees the svfStateMgr facade above).
/// Handle to the underlying state manager. Used by the merged
/// `getAbsValue` / `updateAbsValue` / `loadValue` / `storeValue` / GEP
/// primitives above, and by the harness-only post-trace accessors.
AbstractInterpretation* ai = nullptr;
};

Expand Down
2 changes: 1 addition & 1 deletion Assignment-3/CPP/test-ae.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ int main(int argc, char** argv) {
double wallSeconds = std::chrono::duration<double>(finished - started).count();
if (config.emitJson) {
std::cout << "ASS3_JSON_BEGIN\n";
ae.writeJsonSummary(std::cout, wallSeconds, 0, true);
ae.getReporter().writeJsonSummary(std::cout, pag->getICFG(), wallSeconds, 0, true);
std::cout << "ASS3_JSON_END\n";
}

Expand Down
Loading
Loading