Skip to content

Commit

Permalink
mark function calls with wrong number of arguments as UB
Browse files Browse the repository at this point in the history
  • Loading branch information
nunoplopes committed Apr 10, 2024
1 parent f19cf14 commit 26dbc72
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 15 deletions.
4 changes: 4 additions & 0 deletions ir/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ bool Type::isAggregateType() const {
return isArrayType() || isStructType() || isVectorType();
}

bool Type::isVoid() const {
return this == &voidTy;
}

expr Type::enforceIntType(unsigned bits) const {
return false;
}
Expand Down
1 change: 1 addition & 0 deletions ir/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class Type {
virtual bool isStructType() const;
virtual bool isVectorType() const;
bool isAggregateType() const;
bool isVoid() const;

virtual smt::expr enforceIntType(unsigned bits = 0) const;
smt::expr enforceIntOrPtrType() const;
Expand Down
4 changes: 0 additions & 4 deletions ir/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ namespace IR {

VoidValue Value::voidVal;

bool Value::isVoid() const {
return &getType() == &Type::voidTy;
}

void Value::rauw(const Value &what, Value &with) {
UNREACHABLE();
}
Expand Down
2 changes: 1 addition & 1 deletion ir/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Value {
auto bits() const { return type.bits(); }
auto& getName() const { return name; }
auto& getType() const { return type; }
bool isVoid() const;
bool isVoid() const { return type.isVoid(); }

virtual void rauw(const Value &what, Value &with);
virtual void print(std::ostream &os) const = 0;
Expand Down
27 changes: 21 additions & 6 deletions llvm_util/llvm2alive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
return make_unique<Assume>(*true_val, Assume::AndNonPoison);
}

RetTy mkUnreach() {
return make_unique<Assume>(*make_intconst(0, 1), Assume::AndNonPoison);
}

public:
llvm2alive_(llvm::Function &f, const llvm::TargetLibraryInfo &TLI, bool IsSrc,
const vector<string_view> &gvnamesInSrc)
Expand Down Expand Up @@ -360,6 +364,10 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
attrs.set(FnAttrs::NNaN);
}

auto ty = llvm_type2alive(i.getType());
if (!ty)
return error(i);

// record fn decl in case there are indirect calls to this function
// elsewhere
auto fn_decl = fn;
Expand Down Expand Up @@ -388,6 +396,18 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
if (!(decl.output = llvm_type2alive(fn_decl->getReturnType())))
return error(i);

// it's UB if there's a mismatch in the number of function arguments
if (( fn_decl->isVarArg() && i.arg_size() < fn_decl->arg_size()) ||
(!fn_decl->isVarArg() && i.arg_size() != fn_decl->arg_size())) {
auto unreach = mkUnreach();
if (ty->isVoid())
return unreach;
BB->addInstr(std::move(unreach));
RETURN_IDENTIFIER(
make_unique<UnaryOp>(*ty, value_name(i), *get_poison(*ty),
UnaryOp::Copy));
}

auto attrs_fndef = fn_decl->getAttributes();
for (uint64_t idx = 0, nargs = fn_decl->arg_size(); idx < nargs; ++idx) {
auto ty = llvm_type2alive(fn_decl->getArg(idx)->getType());
Expand All @@ -414,10 +434,6 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
RETURN_IDENTIFIER(std::move(known));
}

auto ty = llvm_type2alive(i.getType());
if (!ty)
return error(i);

unique_ptr<FnCall> call;
Value *fnptr = nullptr;

Expand Down Expand Up @@ -721,8 +737,7 @@ class llvm2alive_ : public llvm::InstVisitor<llvm2alive_, unique_ptr<Instr>> {
}

RetTy visitUnreachableInst(llvm::UnreachableInst &i) {
auto fals = get_operand(llvm::ConstantInt::getFalse(i.getContext()));
return make_unique<Assume>(*fals, Assume::AndNonPoison);
return mkUnreach();
}

enum LifetimeKind {
Expand Down
12 changes: 8 additions & 4 deletions llvm_util/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,13 @@ IR::Value* make_intconst(const llvm::APInt &val) {
return ret;
}

IR::Value* get_poison(Type &ty) {
auto val = make_unique<PoisonValue>(ty);
auto ret = val.get();
current_fn->addConstant(std::move(val));
return ret;
}

#define RETURN_CACHE(val) \
do { \
auto val_cpy = val; \
Expand Down Expand Up @@ -295,10 +302,7 @@ Value* get_operand(llvm::Value *v,
}

if (isa<llvm::PoisonValue>(v)) {
auto val = make_unique<PoisonValue>(*ty);
auto ret = val.get();
current_fn->addConstant(std::move(val));
RETURN_CACHE(ret);
RETURN_CACHE(get_poison(*ty));
}

if (isa<llvm::UndefValue>(v)) {
Expand Down
1 change: 1 addition & 0 deletions llvm_util/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ IR::Type* llvm_type2alive(const llvm::Type *ty);

IR::Value* make_intconst(uint64_t val, int bits);
IR::Value* make_intconst(const llvm::APInt &val);
IR::Value* get_poison(IR::Type &ty);
IR::Value* get_operand(llvm::Value *v,
std::function<IR::Value*(llvm::ConstantExpr *)> constexpr_conv,
std::function<IR::Value*(IR::AggregateValue *)> copy_inserter);
Expand Down

0 comments on commit 26dbc72

Please sign in to comment.