@@ -623,6 +623,54 @@ handleUserSection(const NewSectionInfo &NewSection,
623623 return F (NewSection.SectionName , Data);
624624}
625625
626+ static Error verifyNoteSection (StringRef Name, endianness Endianness,
627+ ArrayRef<uint8_t > Data) {
628+ // An ELF note has the following structure:
629+ // Name Size: 4 bytes (integer)
630+ // Desc Size: 4 bytes (integer)
631+ // Type : 4 bytes
632+ // Name : variable size, padded to a 4 byte boundary
633+ // Desc : variable size, padded to a 4 byte boundary
634+
635+ if (Data.empty ())
636+ return Error::success ();
637+
638+ if (Data.size () < 12 ) {
639+ std::string msg;
640+ raw_string_ostream (msg)
641+ << Name << " data must be either empty or at least 12 bytes long" ;
642+ return createStringError (errc::invalid_argument, msg);
643+ }
644+ if (Data.size () % 4 != 0 ) {
645+ std::string msg;
646+ raw_string_ostream (msg)
647+ << Name << " data size must be a multiple of 4 bytes" ;
648+ return createStringError (errc::invalid_argument, msg);
649+ }
650+ ArrayRef<uint8_t > NameSize = Data.slice (0 , 4 );
651+ ArrayRef<uint8_t > DescSize = Data.slice (4 , 4 );
652+
653+ uint32_t NameSizeValue = support::endian::read32 (NameSize.data (), Endianness);
654+ uint32_t DescSizeValue = support::endian::read32 (DescSize.data (), Endianness);
655+
656+ uint64_t ExpectedDataSize =
657+ /* NameSize=*/ 4 + /* DescSize=*/ 4 + /* Type=*/ 4 +
658+ /* Name=*/ alignTo (NameSizeValue, 4 ) +
659+ /* Desc=*/ alignTo (DescSizeValue, 4 );
660+ uint64_t ActualDataSize = Data.size ();
661+ if (ActualDataSize != ExpectedDataSize) {
662+ std::string msg;
663+ raw_string_ostream (msg)
664+ << Name
665+ << " data size is incompatible with the content of "
666+ " the name and description size fields:"
667+ << " expecting " << ExpectedDataSize << " , found " << ActualDataSize;
668+ return createStringError (errc::invalid_argument, msg);
669+ }
670+
671+ return Error::success ();
672+ }
673+
626674// This function handles the high level operations of GNU objcopy including
627675// handling command line options. It's important to outline certain properties
628676// we expect to hold of the command line operations. Any operation that "keeps"
@@ -631,7 +679,7 @@ handleUserSection(const NewSectionInfo &NewSection,
631679// depend a) on the order the options occur in or b) on some opaque priority
632680// system. The only priority is that keeps/copies overrule removes.
633681static Error handleArgs (const CommonConfig &Config, const ELFConfig &ELFConfig,
634- Object &Obj) {
682+ ElfType OutputElfType, Object &Obj) {
635683 if (Config.OutputArch ) {
636684 Obj.Machine = Config.OutputArch ->EMachine ;
637685 Obj.OSABI = Config.OutputArch ->OSABI ;
@@ -702,12 +750,19 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
702750 if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
703751 Sec.Type = SHT_NOBITS;
704752
753+ endianness E = OutputElfType == ELFT_ELF32LE || OutputElfType == ELFT_ELF64LE
754+ ? endianness::little
755+ : endianness::big;
756+
705757 for (const NewSectionInfo &AddedSection : Config.AddSection ) {
706- auto AddSection = [&](StringRef Name, ArrayRef<uint8_t > Data) {
758+ auto AddSection = [&](StringRef Name, ArrayRef<uint8_t > Data) -> Error {
707759 OwnedDataSection &NewSection =
708760 Obj.addSection <OwnedDataSection>(Name, Data);
709- if (Name.starts_with (" .note" ) && Name != " .note.GNU-stack" )
761+ if (Name.starts_with (" .note" ) && Name != " .note.GNU-stack" ) {
710762 NewSection.Type = SHT_NOTE;
763+ if (ELFConfig.VerifyNoteSections )
764+ return verifyNoteSection (Name, E, Data);
765+ }
711766 return Error::success ();
712767 };
713768 if (Error E = handleUserSection (AddedSection, AddSection))
@@ -840,7 +895,7 @@ Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,
840895
841896 const ElfType OutputElfType =
842897 getOutputElfType (Config.OutputArch .value_or (MachineInfo ()));
843- if (Error E = handleArgs (Config, ELFConfig, **Obj))
898+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
844899 return E;
845900 return writeOutput (Config, **Obj, Out, OutputElfType);
846901}
@@ -858,7 +913,7 @@ Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
858913 // (-B<arch>).
859914 const ElfType OutputElfType =
860915 getOutputElfType (Config.OutputArch .value_or (MachineInfo ()));
861- if (Error E = handleArgs (Config, ELFConfig, **Obj))
916+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
862917 return E;
863918 return writeOutput (Config, **Obj, Out, OutputElfType);
864919}
@@ -877,7 +932,7 @@ Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
877932 ? getOutputElfType (*Config.OutputArch )
878933 : getOutputElfType (In);
879934
880- if (Error E = handleArgs (Config, ELFConfig, **Obj))
935+ if (Error E = handleArgs (Config, ELFConfig, OutputElfType, **Obj))
881936 return createFileError (Config.InputFilename , std::move (E));
882937
883938 if (Error E = writeOutput (Config, **Obj, Out, OutputElfType))
0 commit comments