Skip to content

Commit

Permalink
[FuzzMutate] Allow only sized pointers for the GEP instruction
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D40837

llvm-svn: 320032
igor-laevsky committed Dec 7, 2017
1 parent 72281a2 commit e8a3475
Showing 3 changed files with 66 additions and 1 deletion.
18 changes: 18 additions & 0 deletions llvm/include/llvm/FuzzMutate/OpDescriptor.h
Original file line number Diff line number Diff line change
@@ -140,6 +140,24 @@ static inline SourcePred anyPtrType() {
return {Pred, Make};
}

static inline SourcePred sizedPtrType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
return PtrT->getElementType()->isSized();
return false;
};
auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
std::vector<Constant *> Result;

for (Type *T : Ts)
if (T->isSized())
Result.push_back(UndefValue::get(PointerType::getUnqual(T)));

return Result;
};
return {Pred, Make};
}

static inline SourcePred anyAggregateType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
return V->getType()->isAggregateType();
2 changes: 1 addition & 1 deletion llvm/lib/FuzzMutate/Operations.cpp
Original file line number Diff line number Diff line change
@@ -172,7 +172,7 @@ OpDescriptor llvm::fuzzerop::gepDescriptor(unsigned Weight) {
// TODO: Handle aggregates and vectors
// TODO: Support multiple indices.
// TODO: Try to avoid meaningless accesses.
return {Weight, {anyPtrType(), anyIntType()}, buildGEP};
return {Weight, {sizedPtrType(), anyIntType()}, buildGEP};
}

static uint64_t getAggregateNumElements(Type *T) {
47 changes: 47 additions & 0 deletions llvm/unittests/FuzzMutate/OperationsTest.cpp
Original file line number Diff line number Diff line change
@@ -8,11 +8,13 @@
//===----------------------------------------------------------------------===//

#include "llvm/FuzzMutate/Operations.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/FuzzMutate/OpDescriptor.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/SourceMgr.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <iostream>
@@ -52,9 +54,25 @@ using testing::NotNull;
using testing::PrintToString;
using testing::SizeIs;

namespace {
std::unique_ptr<Module> parseAssembly(
const char *Assembly, LLVMContext &Context) {

SMDiagnostic Error;
std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);

std::string ErrMsg;
raw_string_ostream OS(ErrMsg);
Error.print("", OS);

assert(M && !verifyModule(*M, &errs()));
return M;
}

MATCHER_P(TypesMatch, V, "has type " + PrintToString(V->getType())) {
return arg->getType() == V->getType();
}

MATCHER_P(HasType, T, "") { return arg->getType() == T; }

TEST(OperationsTest, SourcePreds) {
@@ -253,6 +271,33 @@ TEST(OperationsTest, GEP) {
EXPECT_FALSE(verifyModule(M, &errs()));
}


TEST(OperationsTest, GEPPointerOperand) {
// Check that we only pick sized pointers for the GEP instructions

LLVMContext Ctx;
const char *SourceCode =
"declare void @f()\n"
"define void @test() {\n"
" %v = bitcast void ()* @f to i64 (i8 addrspace(4)*)*\n"
" %a = alloca i64, i32 10\n"
" ret void\n"
"}";
auto M = parseAssembly(SourceCode, Ctx);

fuzzerop::OpDescriptor Descr = fuzzerop::gepDescriptor(1);

// Get first basic block of the test function
Function &F = *M->getFunction("test");
BasicBlock &BB = *F.begin();

// Don't match %v
ASSERT_FALSE(Descr.SourcePreds[0].matches({}, &*BB.begin()));

// Match %a
ASSERT_TRUE(Descr.SourcePreds[0].matches({}, &*std::next(BB.begin())));
}

TEST(OperationsTest, ExtractAndInsertValue) {
LLVMContext Ctx;

@@ -321,3 +366,5 @@ TEST(OperationsTest, ExtractAndInsertValue) {
IVOp.SourcePreds[2].generate({SVal, ConstantInt::get(Int32Ty, 0)}, {}),
ElementsAre(ConstantInt::get(Int32Ty, 1)));
}

}

0 comments on commit e8a3475

Please sign in to comment.