Commit 8f1664fa authored by xqiuyx's avatar xqiuyx
Browse files

fix : 修复GEP索引问题

No related merge requests found
Showing with 70 additions and 44 deletions
+70 -44
......@@ -97,4 +97,8 @@ class PtrChecker {
CheckerResult checkHeapOverflow(const MemoryRegionPtr& region,
const llvm::Instruction* inst,
const SymExprPtr& accessSize);
CheckerResult recursiveCheckHeapOverflow(
const MemoryRegionPtr& region, const llvm::Instruction* inst,
const SymExprPtr& accessSize, SymExprPtr cumulativeOffset = nullptr);
};
\ No newline at end of file
......@@ -12,6 +12,17 @@ class MemoryRegion {
virtual ~MemoryRegion() = default;
virtual Kind getKind() const = 0;
explicit MemoryRegion(SymExprPtr size) : size(std::move(size)) {}
std::string getKindString() const {
switch (getKind()) {
case Kind::Symbolic:
return "Symbolic";
case Kind::Var:
return "Var";
case Kind::Element:
return "Element";
}
return "Unknown";
}
};
using MemoryRegionPtr = std::shared_ptr<MemoryRegion>;
......
......@@ -131,45 +131,53 @@ CheckerResult PtrChecker::checkDoubleFree(const MemoryRegionPtr& region,
1. Var/Symbolic Region 这种情况只需要考虑accessSize,size的大小
2. Element Region 这种情况需要考虑accessSize,size以及offset的大小
*/
CheckerResult PtrChecker::checkHeapOverflow(const MemoryRegionPtr& region,
const llvm::Instruction* inst,
const SymExprPtr& accessSize) {
switch (region->getKind()) {
case MemoryRegion::Kind::Var:
case MemoryRegion::Kind::Symbolic: {
// 出界判断: size < accessSize
auto bool_sym = state_.createCompare(region->size, accessSize,
CompareSymExpr::Op::Lt);
if (state_.isFeasible(bool_sym)) {
// 如果size是不确定的值,只输出警告,因为无法准确判断是否会溢出,只是可能移除
if (region->size->unknown) {
return CheckerResult::Warning("Heap overflow", inst);
}
return CheckerResult::Error("Heap overflow", inst);
}
break;
}
case MemoryRegion::Kind::Element: {
// 出界判断: base(size) < accessSize + offset
auto element_region =
std::dynamic_pointer_cast<ElementRegion>(region);
auto bool_sym = state_.createCompare(
element_region->base->size,
state_.createBinary(accessSize, element_region->offset,
BinarySymExpr::Op::Add),
CompareSymExpr::Op::Lt);
if (state_.isFeasible(bool_sym)) {
if (bool_sym->unknown) {
return CheckerResult::Warning(
"Heap overflow" + getInstructionWithDebugInfo(inst),
inst);
}
return CheckerResult::Error(
"Heap overflow" + getInstructionWithDebugInfo(inst), inst);
}
break;
}
CheckerResult PtrChecker::recursiveCheckHeapOverflow(
const MemoryRegionPtr& region, const llvm::Instruction* inst,
const SymExprPtr& accessSize, SymExprPtr cumulativeOffset) {
// 初始化累积偏移量
if (!cumulativeOffset) {
cumulativeOffset = state_.createConst(0);
}
// 递归检查每一层是否越界,即 当前层(size) < cumulativeOffset + accessSize && cumulativeOffset + accessSize > 0
// LOG_WARN << "Check heap overflow: " << region->getKindString()
// << " cumulativeOffset: " << cumulativeOffset->toString()
// << " accessSize: " << accessSize->toString();
auto off_add_access = state_.createBinary(cumulativeOffset, accessSize,
BinarySymExpr::Op::Add);
auto size = region->size;
// 是否可能溢出
auto size_check =
state_.createCompare(off_add_access, size, CompareSymExpr::Op::Gt);
if (state_.isFeasible(size_check)) {
return CheckerResult::Error("Heap overflow", inst);
}
// 是否可能小于0
auto down_check = state_.createCompare(
off_add_access, state_.createConst(0), CompareSymExpr::Op::Lt);
if (state_.isFeasible(down_check)) {
return CheckerResult::Error("Index is less than zero ", inst);
}
// 然后如果是ElementRegion,叠加偏移量cumulativeOffset += offset,递归检查base
if (region->getKind() == MemoryRegion::Kind::Element) {
auto element_region = std::static_pointer_cast<ElementRegion>(region);
auto offset = element_region->offset;
auto new_cumulative_offset = state_.createBinary(
cumulativeOffset, offset, BinarySymExpr::Op::Add);
auto base = element_region->base;
return recursiveCheckHeapOverflow(base, inst, accessSize,
new_cumulative_offset);
}
return CheckerResult::Success();
}
\ No newline at end of file
}
CheckerResult PtrChecker::checkHeapOverflow(const MemoryRegionPtr& region,
const llvm::Instruction* inst,
const SymExprPtr& accessSize) {
// 使用递归检查所有嵌套的ElementRegion
return recursiveCheckHeapOverflow(region, inst, accessSize);
}
......@@ -78,7 +78,7 @@ SymExprPtr GetGEPOffsetExpr(llvm::GetElementPtrInst* GepInst,
s = offset_expr;
} else {
for (unsigned i = 1; i < GepInst->getNumIndices(); i++) {
auto* index = GepInst->getOperand(i);
auto* index = GepInst->getOperand(i + 1);
auto index_expr = ps_.value2SymExprOrNew(index);
uint64_t type_size = 0;
if (auto* st = llvm::dyn_cast<llvm::StructType>(current_type)) {
......@@ -239,13 +239,16 @@ void TransferVisitor::handleGetElementPtrInst(
auto* ptr = GepInst->getPointerOperand();
auto ptr_expr = ps_.envLookup(ptr);
ps_.checkPtr(GepInst, ptr_expr, BaseFlag);
auto base_loc = getLocFromPtr(ptr_expr);
// Create a new region for the GEP
uint64_t element_size =
ps_.DL.getTypeStoreSize(GepInst->getResultElementType());
auto size_expr = ps_.createConst(element_size);
auto element_region =
ps_.createElementRegion(base_loc, offset_expr, ps_.createConst(0));
// Create a new LocSymExpr for the GEP
ps_.createElementRegion(base_loc, offset_expr, size_expr);
// 创建新的位置表达式并绑定
auto loc_expr = ps_.createLoc(element_region);
// Bind the loc to the environment
ps_.envBind(GepInst, loc_expr);
}
void TransferVisitor::handleSExtInst(llvm::SExtInst* sextInst) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment