Skip to content

Commit 8a386fe

Browse files
authored
[FuzzMutate] Prevent UB caused by parameter ABI attributes (#139737)
This PR prevents the IRMutator from incorrectly calling functions that have ABI attributes, otherwise the mutations introduce UB.
1 parent 578c75e commit 8a386fe

File tree

1 file changed

+58
-10
lines changed

1 file changed

+58
-10
lines changed

llvm/lib/FuzzMutate/IRMutator.cpp

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,62 @@ static uint64_t getUniqueCaseValue(SmallSet<uint64_t, 4> &CasesTaken,
356356
return tmp;
357357
}
358358

359+
/// Determines whether a function is unsupported by the current mutator's
360+
/// implementation. The function returns true if any of the following criteria
361+
/// are met:
362+
/// * The function accepts metadata or token types as arguments.
363+
/// * The function has ABI attributes that could cause UB.
364+
/// * The function uses a non-callable CC that may result in UB.
365+
static bool isUnsupportedFunction(Function *F) {
366+
// Some functions accept metadata type or token type as arguments.
367+
// We don't call those functions for now.
368+
// For example, `@llvm.dbg.declare(metadata, metadata, metadata)`
369+
// https://llvm.org/docs/SourceLevelDebugging.html#llvm-dbg-declare
370+
auto IsUnsupportedTy = [](Type *T) {
371+
return T->isMetadataTy() || T->isTokenTy();
372+
};
373+
374+
if (IsUnsupportedTy(F->getReturnType()) ||
375+
any_of(F->getFunctionType()->params(), IsUnsupportedTy)) {
376+
return true;
377+
}
378+
379+
// ABI attributes must be specified both at the function
380+
// declaration/definition and call-site, otherwise the
381+
// behavior may be undefined.
382+
// We don't call those functions for now to prevent UB from happening.
383+
auto IsABIAttribute = [](AttributeSet A) {
384+
static const Attribute::AttrKind ABIAttrs[] = {
385+
Attribute::StructRet, Attribute::ByVal,
386+
Attribute::InAlloca, Attribute::InReg,
387+
Attribute::StackAlignment, Attribute::SwiftSelf,
388+
Attribute::SwiftAsync, Attribute::SwiftError,
389+
Attribute::Preallocated, Attribute::ByRef,
390+
Attribute::ZExt, Attribute::SExt};
391+
392+
return std::any_of(
393+
std::begin(ABIAttrs), std::end(ABIAttrs),
394+
[&](Attribute::AttrKind kind) { return A.hasAttribute(kind); });
395+
};
396+
397+
auto FuncAttrs = F->getAttributes();
398+
if (IsABIAttribute(FuncAttrs.getRetAttrs())) {
399+
return true;
400+
}
401+
for (size_t i = 0; i < F->arg_size(); i++) {
402+
if (IsABIAttribute(FuncAttrs.getParamAttrs(i))) {
403+
return true;
404+
}
405+
}
406+
407+
// If it is not satisfied, the IR will be invalid.
408+
if (!isCallableCC(F->getCallingConv())) {
409+
return true;
410+
}
411+
412+
return false;
413+
}
414+
359415
void InsertFunctionStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
360416
Module *M = BB.getParent()->getParent();
361417
// If nullptr is selected, we will create a new function declaration.
@@ -366,16 +422,8 @@ void InsertFunctionStrategy::mutate(BasicBlock &BB, RandomIRBuilder &IB) {
366422

367423
auto RS = makeSampler(IB.Rand, Functions);
368424
Function *F = RS.getSelection();
369-
// Some functions accept metadata type or token type as arguments.
370-
// We don't call those functions for now.
371-
// For example, `@llvm.dbg.declare(metadata, metadata, metadata)`
372-
// https://llvm.org/docs/SourceLevelDebugging.html#llvm-dbg-declare
373-
auto IsUnsupportedTy = [](Type *T) {
374-
return T->isMetadataTy() || T->isTokenTy();
375-
};
376-
if (!F || IsUnsupportedTy(F->getReturnType()) ||
377-
any_of(F->getFunctionType()->params(), IsUnsupportedTy) ||
378-
!isCallableCC(F->getCallingConv())) {
425+
426+
if (!F || isUnsupportedFunction(F)) {
379427
F = IB.createFunctionDeclaration(*M);
380428
}
381429

0 commit comments

Comments
 (0)