From 4eaf3a7596fb335edfa36368c2851a256b6e8d75 Mon Sep 17 00:00:00 2001 From: SivanShani-Arm Date: Mon, 14 Apr 2025 14:23:00 +0100 Subject: [PATCH] [readobj][ELF][AArch64] Handle misformed AArch64 build attribute section (#134888) Report an error when the .ARM.attributes section for AArch64 is malformed or violates expected format. --- llvm/lib/Support/ELFAttrParserExtended.cpp | 34 +++++++++++++++++-- .../AArch64/build-attributes-melformed-long.s | 24 +++++++++++++ .../build-attributes-melformed-short.s | 24 +++++++++++++ .../AArch64/build-attributes-melformed-type.s | 27 +++++++++++++++ .../build-attributes-melformed-values.s | 24 +++++++++++++ .../AArch64/build-attributes-melformed-ver.s | 23 +++++++++++++ 6 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-long.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-short.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-type.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-values.s create mode 100644 llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-ver.s diff --git a/llvm/lib/Support/ELFAttrParserExtended.cpp b/llvm/lib/Support/ELFAttrParserExtended.cpp index c08ed5e6fe86..f98905b6171c 100644 --- a/llvm/lib/Support/ELFAttrParserExtended.cpp +++ b/llvm/lib/Support/ELFAttrParserExtended.cpp @@ -103,6 +103,8 @@ Error ELFExtendedAttrParser::parse(ArrayRef Section, // Get format-version uint8_t FormatVersion = De.getU8(Cursor); + if (!Cursor) + return Cursor.takeError(); if (ELFAttrs::Format_Version != FormatVersion) return createStringError(errc::invalid_argument, "unrecognized format-version: 0x" + @@ -110,19 +112,39 @@ Error ELFExtendedAttrParser::parse(ArrayRef Section, while (!De.eof(Cursor)) { uint32_t ExtBASubsectionLength = De.getU32(Cursor); - // Minimal valid Extended Build Attributes subsection header size is at + if (!Cursor) + return Cursor.takeError(); + // Minimal valid Extended Build Attributes subsection size is at // least 8: length(4) name(at least a single char + null) optionality(1) and // type(1) - if (ExtBASubsectionLength < 8) + // Extended Build Attributes subsection has to fit inside the section. + if (ExtBASubsectionLength < 8 || + ExtBASubsectionLength > (Section.size() - Cursor.tell() + 4)) return createStringError( errc::invalid_argument, "invalid Extended Build Attributes subsection size at offset: " + utohexstr(Cursor.tell() - 4)); StringRef VendorName = De.getCStrRef(Cursor); + if (!Cursor) + return Cursor.takeError(); uint8_t IsOptional = De.getU8(Cursor); + if (!Cursor) + return Cursor.takeError(); + if (!(0 == IsOptional || 1 == IsOptional)) + return createStringError( + errc::invalid_argument, + "\ninvalid Optionality at offset " + utohexstr(Cursor.tell() - 4) + + ": " + utohexstr(IsOptional) + " (Options are 1|0)"); StringRef IsOptionalStr = IsOptional ? "optional" : "required"; uint8_t Type = De.getU8(Cursor); + if (!Cursor) + return Cursor.takeError(); + if (!(0 == Type || 1 == Type)) + return createStringError(errc::invalid_argument, + "\ninvalid Type at offset " + + utohexstr(Cursor.tell() - 4) + ": " + + utohexstr(Type) + " (Options are 1|0)"); StringRef TypeStr = Type ? "ntbs" : "uleb128"; BuildAttributeSubSection BASubSection; @@ -144,12 +166,14 @@ Error ELFExtendedAttrParser::parse(ArrayRef Section, // Offset in Section uint64_t OffsetInSection = Cursor.tell(); // Size: 4 bytes, Vendor Name: VendorName.size() + 1 (null termination), - // optionality: 1, size: 1 + // optionality: 1, type: 1 uint32_t BytesAllButAttributes = 4 + (VendorName.size() + 1) + 1 + 1; while (Cursor.tell() < (OffsetInSection + ExtBASubsectionLength - BytesAllButAttributes)) { uint64_t Tag = De.getULEB128(Cursor); + if (!Cursor) + return Cursor.takeError(); StringRef TagName = getTagName(VendorName, Tag); @@ -157,10 +181,14 @@ Error ELFExtendedAttrParser::parse(ArrayRef Section, std::string ValueStr = ""; if (Type) { // type==1 --> ntbs ValueStr = De.getCStrRef(Cursor); + if (!Cursor) + return Cursor.takeError(); if (Sw) Sw->printString("" != TagName ? TagName : utostr(Tag), ValueStr); } else { // type==0 --> uleb128 ValueInt = De.getULEB128(Cursor); + if (!Cursor) + return Cursor.takeError(); if (Sw) Sw->printNumber("" != TagName ? TagName : utostr(Tag), ValueInt); } diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-long.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-long.s new file mode 100644 index 000000000000..fff221441edf --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-long.s @@ -0,0 +1,24 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-readobj --arch-specific %t.o %null 2>&1 | FileCheck %s + +# CHECK: unable to dump attributes from the Unknown section with index 1: invalid Extended Build Attributes subsection size at offset: 1A + +# Indicated size is longer than actual size. +# The size is indicated by the '99' in the sequence '...0101020199...' should be 23 +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_NONE + Type: ET_REL + Machine: EM_AARCH64 + Entry: 0x0 + +Sections: + - Name: .ARM.attributes + Type: 0x70000003 # SHT_LOPROC + 3 + AddressAlign: 1 + Offset: 0x40 + Size: 0x3d + Content: "411900000061656162695f7061757468616269000000010102019900000061656162695f666561747572655f616e645f62697473000100000101010201" +... diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-short.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-short.s new file mode 100644 index 000000000000..c79eec8fbb23 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-short.s @@ -0,0 +1,24 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-readobj --arch-specific %t.o %null 2>&1 | FileCheck %s + +# CHECK: unable to dump attributes from the Unknown section with index 1: invalid Extended Build Attributes subsection size at offset: 3B + +# Indicated size is shorter than actual size. +# The size is indicated by the '20' in the sequence '...0101020120...' should be 23 +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_NONE + Type: ET_REL + Machine: EM_AARCH64 + Entry: 0x0 + +Sections: + - Name: .ARM.attributes + Type: 0x70000003 # SHT_LOPROC + 3 + AddressAlign: 1 + Offset: 0x40 + Size: 0x41 + Content: "411900000061656162695f7061757468616269000000010102012000000061656162695f666561747572655f616e645f6269747300010000010101020000" +... diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-type.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-type.s new file mode 100644 index 000000000000..c113fb4dd17d --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-type.s @@ -0,0 +1,27 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-readobj --arch-specific %t.o %null 2>&1 | FileCheck %s + +# CHECK: BuildAttributes { +# CHECK-NEXT: FormatVersion: 0x41 +# CHECK-NEXT: unable to dump attributes from the Unknown section with index 1: +# CHECK-NEXT: invalid Type at offset 12: 9 (Options are 1|0) + +# Type are not 0 or 1 +# Type is indicated by the '09' in the sequence '...69000109...' should be 00 or 01 +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_NONE + Type: ET_REL + Machine: EM_AARCH64 + Entry: 0x0 + +Sections: + - Name: .ARM.attributes + Type: 0x70000003 # SHT_LOPROC + 3 + AddressAlign: 1 + Offset: 0x40 + Size: 0x3d + Content: "411900000061656162695f7061757468616269000109010102012300000061656162695f666561747572655f616e645f62697473000100000101010201" +... diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-values.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-values.s new file mode 100644 index 000000000000..99d7491bdbc4 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-values.s @@ -0,0 +1,24 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-readobj --arch-specific %t.o %null 2>&1 | FileCheck %s + +# CHECK: unable to dump attributes from the Unknown section with index 1: invalid Extended Build Attributes subsection size at offset: 3D + +# ULEB values are overflowing. +# Those are the trailing '000' in the sequence '...00010101020000' should be '...000101010201' +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_NONE + Type: ET_REL + Machine: EM_AARCH64 + Entry: 0x0 + +Sections: + - Name: .ARM.attributes + Type: 0x70000003 # SHT_LOPROC + 3 + AddressAlign: 1 + Offset: 0x40 + Size: 0x41 + Content: "411900000061656162695f7061757468616269000000010102012300000061656162695f666561747572655f616e645f6269747300010000010101020000" +... diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-ver.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-ver.s new file mode 100644 index 000000000000..2495180c3053 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/build-attributes-melformed-ver.s @@ -0,0 +1,23 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-readobj --arch-specific %t.o %null 2>&1 | FileCheck %s + +# CHECK: unable to dump attributes from the Unknown section with index 1: unrecognized format-version: 0x37 + +# Version is 37 instead of 41, this is the first byte. +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + OSABI: ELFOSABI_NONE + Type: ET_REL + Machine: EM_AARCH64 + Entry: 0x0 + +Sections: + - Name: .ARM.attributes + Type: 0x70000003 # SHT_LOPROC + 3 + AddressAlign: 1 + Offset: 0x40 + Size: 0x3d + Content: "371900000061656162695f7061757468616269000000010102012300000061656162695f666561747572655f616e645f62697473000100000101010201" +...