diff --git a/src/patchelf.cc b/src/patchelf.cc index fd1e7b7b..75df70cf 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -501,7 +501,7 @@ void ElfFile::sortShdrs() info[getSectionName(shdrs[i])] = getSectionName(shdrs[rdi(shdrs[i].sh_info)]); /* Idem for the index of the .shstrtab section in the ELF header. */ - SectionName shstrtabName = getSectionName(shdrs[rdi(hdr->e_shstrndx)]); + Elf_Shdr shstrtab = shdrs[rdi(hdr->e_shstrndx)]; /* Sort the sections by offset. */ CompShdr comp; @@ -521,8 +521,14 @@ void ElfFile::sortShdrs() wri(shdrs[i].sh_info, findSection3(info[getSectionName(shdrs[i])])); - /* And the .shstrtab index. */ - wri(hdr->e_shstrndx, findSection3(shstrtabName)); + /* And the .shstrtab index. Note: the match here is done by checking the offset as searching + * by name can yield incorrect results in case there are multiple sections with the same + * name as the one initially pointed by hdr->e_shstrndx */ + for (unsigned int i = 1; i < rdi(hdr->e_shnum); ++i) { + if (shdrs[i].sh_offset == shstrtab.sh_offset) { + wri(hdr->e_shstrndx, i); + } + } } static void writeFile(const std::string & fileName, const FileContents & contents) diff --git a/tests/Makefile.am b/tests/Makefile.am index f8176e03..eb77313e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ LIBS = -check_PROGRAMS = simple main main-scoped big-dynstr no-rpath contiguous_note_sections +check_PROGRAMS = simple main too-many-strtab main-scoped big-dynstr no-rpath contiguous_note_sections no_rpath_arch_TESTS = \ no-rpath-amd64.sh \ @@ -25,6 +25,7 @@ src_TESTS = \ force-rpath.sh \ plain-needed.sh \ output-flag.sh \ + too-many-strtab.sh \ no-rpath-pie-powerpc.sh \ build-id.sh \ invalid-elf.sh \ @@ -81,7 +82,7 @@ big_dynstr_LDFLAGS = $(LDFLAGS_local) # - without libtool, only archives (static libraries) can be built by automake # - with libtool, it is difficult to control options # - with libtool, it is not possible to compile convenience *dynamic* libraries :-( -check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so libbuildid.so +check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so libbuildid.so libtoomanystrtab.so libbuildid_so_SOURCES = simple.c libbuildid_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-build-id @@ -105,6 +106,9 @@ libbar_scoped_so_LDFLAGS = $(LDFLAGS_sharedlib) libsimple_so_SOURCES = simple.c libsimple_so_LDFLAGS = $(LDFLAGS_sharedlib) +libtoomanystrtab_so_SOURCES = too-many-strtab.c +libtoomanystrtab_so_LDFLAGS = $(LDFLAGS_sharedlib) + no_rpath_SOURCES = no-rpath.c # no -fpic for no-rpath.o no_rpath_CFLAGS = diff --git a/tests/too-many-strtab.c b/tests/too-many-strtab.c new file mode 100644 index 00000000..0f513168 --- /dev/null +++ b/tests/too-many-strtab.c @@ -0,0 +1,3 @@ +const int __attribute__((section (".shstrtab"))) lel = 42; + +int main(){return 0;} diff --git a/tests/too-many-strtab.sh b/tests/too-many-strtab.sh new file mode 100755 index 00000000..3ef158f7 --- /dev/null +++ b/tests/too-many-strtab.sh @@ -0,0 +1,21 @@ +#! /bin/sh -e +SCRATCH=scratch/$(basename $0 .sh) + +rm -rf ${SCRATCH} +mkdir -p ${SCRATCH} + +cp libtoomanystrtab.so ${SCRATCH}/ + +# Set a RUNPATH on the library +../src/patchelf --set-rpath '$ORIGIN' ${SCRATCH}/libtoomanystrtab.so + +# Check that patchelf is able to patch it again without crashing. Previously, +# it will wrongly identify the lib as a static object because there was no +# .dynamic section +exitCode=0 +(../src/patchelf --set-rpath '$ORIGIN' ${SCRATCH}/libtoomanystrtab.so) || exitCode=$? +if test "$exitCode" != 0; then + echo "bad exit code!" + exit 1 +fi +