Skip to content
Open
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
24 changes: 24 additions & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,7 @@ void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) {
static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); }
static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); }
static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); }
static bool isMDTuple(const Metadata *MD) { return !MD || isa<MDTuple>(MD); }

void Verifier::visitDILocation(const DILocation &N) {
CheckDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
Expand Down Expand Up @@ -1320,6 +1321,29 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
CheckDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,
N.getRawExtraData());
} else if (N.getTag() == dwarf::DW_TAG_template_alias) {
CheckDI(isMDTuple(N.getRawExtraData()), "invalid template parameters", &N,
N.getRawExtraData());
} else if (auto *ExtraData = N.getRawExtraData()) {
auto IsValidExtraData = [&]() {
if (isa<ConstantAsMetadata>(ExtraData) || isa<MDString>(ExtraData) ||
isa<DIObjCProperty>(ExtraData))
return true;
if (auto *Tuple = dyn_cast<MDTuple>(ExtraData)) {
if (N.getTag() != dwarf::DW_TAG_inheritance &&
N.getTag() != dwarf::DW_TAG_member &&
N.getTag() != dwarf::DW_TAG_variable)
return false;
if (Tuple->getNumOperands() != 1)
return false;
return isa_and_nonnull<ConstantAsMetadata>(Tuple->getOperand(0).get());
}
return false;
};
CheckDI(IsValidExtraData(),
"extraData must be ConstantAsMetadata, MDString, DIObjCProperty, "
"or MDTuple with single ConstantAsMetadata operand",
&N, ExtraData);
}

if (N.getTag() == dwarf::DW_TAG_set_type) {
Expand Down
66 changes: 66 additions & 0 deletions llvm/test/Verifier/diderivedtype-extradata-tuple.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
; RUN: not opt -S < %s 2>&1 | FileCheck %s

;; Test that extraData with MDTuple is only allowed for specific DWARF tags:
;; DW_TAG_inheritance, DW_TAG_member, and DW_TAG_variable

!llvm.module.flags = !{!0}
!0 = !{i32 2, !"Debug Info Version", i32 3}

!1 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)

; Keep all metadata nodes alive so verifier can check them
!named = !{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19}
!2 = !{i32 0}

; Valid: DW_TAG_inheritance with tuple extraData should be accepted
!3 = !DIDerivedType(tag: DW_TAG_inheritance, baseType: !1, size: 32, extraData: !2)

; Valid: DW_TAG_member with tuple extraData should be accepted
!4 = !DIDerivedType(tag: DW_TAG_member, name: "field", baseType: !1, size: 32, extraData: !2)

; Valid: DW_TAG_variable (static member) with tuple extraData should be accepted
!5 = !DIDerivedType(tag: DW_TAG_variable, name: "var", baseType: !1, extraData: !2, flags: DIFlagStaticMember)

; Invalid: DW_TAG_typedef with tuple extraData should be rejected
; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_typedef
!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy", baseType: !1, extraData: !2)

; Invalid: Empty tuple should be rejected
!7 = !{}
; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
!8 = !DIDerivedType(tag: DW_TAG_member, name: "field2", baseType: !1, extraData: !7)

; Invalid: Tuple with multiple operands should be rejected
!9 = !{i32 0, i32 1}
; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
!10 = !DIDerivedType(tag: DW_TAG_member, name: "field3", baseType: !1, extraData: !9)

; Invalid: Tuple with non-ConstantAsMetadata operand should be rejected
!11 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
!12 = !{!11}
; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
!13 = !DIDerivedType(tag: DW_TAG_member, name: "field4", baseType: !1, extraData: !12)

; Valid: ConstantAsMetadata as extraData should still work for any tag
!14 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy2", baseType: !1, extraData: i32 42)

; Valid: MDString as extraData should still work for any tag
!15 = !DIDerivedType(tag: DW_TAG_typedef, name: "IntTy3", baseType: !1, extraData: !"some string")

; Valid: DW_TAG_template_alias with proper template parameters tuple
; Template aliases are handled specially and accept any MDTuple for template parameters
!16 = !DITemplateTypeParameter(name: "T", type: !1)
!17 = !{!16}
!18 = !DIDerivedType(tag: DW_TAG_template_alias, name: "MyAlias", baseType: !1, extraData: !17)

; Invalid: DW_TAG_template_alias with non-tuple extraData should fail
; CHECK: invalid template parameters
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_template_alias
!19 = !DIDerivedType(tag: DW_TAG_template_alias, name: "FailingAlias", baseType: !1, extraData: i32 42)

; CHECK: warning: ignoring invalid debug info

Loading