From abae7858d6552cf76649fa521e777ac6aa557763 Mon Sep 17 00:00:00 2001 From: "Nathaniel J. Smith" Date: Sat, 2 Apr 2016 13:07:57 -0700 Subject: [PATCH] Fix bug in walking .gnu.version_r linked list When writing the code to teach --replace-needed to modify the .gnu.version_r section (gh-85), I misunderstood how the ->vn_next pointers in the Elf_Verneed structs are supposed to be interpreted: I thought they gave an offset from the beginning of the section, but in fact they give an offset relative to the current struct. The resulting bug was very odd: generally, patchelf would complete without signalling an error, but it would only successfully replace filenames that occurred as either the first or second entries in the .gnu.version_r section, while the third or later entries would be left untouched. This commit fixes the interpretation of the ->vn_next pointers, so that now --replace-needed should work correctly even on ELF files with more than two version needed structs. Thanks to @matthew-brett for finding the bug / providing a test case, and to @rmcgibbo for helping me diagnose it. --- src/patchelf.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index 91abc6e..6c53e85 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -1337,7 +1337,7 @@ void ElfFile::replaceNeeded(map& libs) debug("keeping .gnu.version_r entry `%s'\n", file); } // the Elf_Verneed structures form a linked list, so jump to next entry - need = (Elf_Verneed *) (contents + rdi(shdrVersionR.sh_offset) + rdi(need->vn_next)); + need = (Elf_Verneed *) (((char *) need) + rdi(need->vn_next)); --verNeedNum; } }