Repository: NixOS/patchelf (language: python)

Issue:
patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections
### Describe the bug
We're trying to `--replace-needed` on a `.so` library for a new name.

### Steps To Reproduce
1. download & unzip [libswiftCore.so.zip](https://github.com/NixOS/patchelf/files/9397254/libswiftCore.so.zip)
3. run `patchelf --replace-needed libc++_shared.so libc++_shared_24.so libswiftCore.so`
4. observe the error

### Expected behavior
The command should succeed.

### Environment
patchelf 0.15.0 / M1 Pro / mbp 16" 2021 / macOS Monterey 12.5.1 (21G83)

### Additional context
Related to https://github.com/buttaface/swift-android-sdk/issues/65


Discussion / hints:
this problem occurs to me,too!Do you have any ideas to how to fix it?
@Survive2 you should run this from ubuntu (the error only occurs on macOS)

Fix patch:
diff --git a/flake.lock b/flake.lock
index 567877e2..4301e9db 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,11 +2,11 @@
   "nodes": {
     "nixpkgs": {
       "locked": {
-        "lastModified": 1637875414,
-        "narHash": "sha256-Ica++SXFuLyxX9Q7YxhfZulUif6/gwM8AEQYlUxqSgE=",
+        "lastModified": 1659914493,
+        "narHash": "sha256-lkA5X3VNMKirvA+SUzvEhfA7XquWLci+CGi505YFAIs=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "3bea86e918d8b54aa49780505d2d4cd9261413be",
+        "rev": "022caabb5f2265ad4006c1fa5b1ebe69fb0c3faf",
         "type": "github"
       },
       "original": {
diff --git a/src/patchelf.cc b/src/patchelf.cc
index f0b5d923..52f0471d 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -906,6 +906,14 @@ void ElfFile<ElfFileParamNames>::normalizeNoteSegments()
         size_t start_off = rdi(phdr.p_offset);
         size_t curr_off = start_off;
         size_t end_off = start_off + rdi(phdr.p_filesz);
+
+        /* Binaries produced by older patchelf versions may contain empty PT_NOTE segments.
+           For backwards compatibility, if we find one we should ignore it. */
+        bool empty = std::none_of(shdrs.begin(), shdrs.end(),
+            [&](auto & shdr) { return rdi(shdr.sh_offset) >= start_off && rdi(shdr.sh_offset) < end_off; });
+        if (empty)
+            continue;
+
         while (curr_off < end_off) {
             /* Find a section that starts at the current offset. If we can't
                find one, it means the SHT_NOTE sections weren't contiguous


Test patch:
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 600639d9..ba516525 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -42,14 +42,15 @@ src_TESTS = \
   phdr-corruption.sh \
   replace-needed.sh \
   replace-add-needed.sh \
-  add-debug-tag.sh
+  add-debug-tag.sh \
+  empty-note.sh
 
 build_TESTS = \
   $(no_rpath_arch_TESTS)
 
 TESTS = $(src_TESTS) $(build_TESTS)
 
-EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness
+EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness empty-note
 
 TESTS_ENVIRONMENT = PATCHELF_DEBUG=1
 
diff --git a/tests/empty-note b/tests/empty-note
new file mode 100755
index 00000000..d58435e1
Binary files /dev/null and b/tests/empty-note differ
diff --git a/tests/empty-note.sh b/tests/empty-note.sh
new file mode 100755
index 00000000..c127d8cc
--- /dev/null
+++ b/tests/empty-note.sh
@@ -0,0 +1,12 @@
+#! /bin/sh -e
+
+SCRATCH=scratch/$(basename $0 .sh)
+
+rm -rf ${SCRATCH}
+mkdir -p ${SCRATCH}
+cp $(dirname $(readlink -f $0))/empty-note ${SCRATCH}/
+
+# Running --set-interpreter on this binary should not produce the following
+# error:
+# patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections
+../src/patchelf --set-interpreter ld-linux-x86-64.so.2 ${SCRATCH}/empty-note