Преглед изворни кода

Dpkg::Shlibs: Preserve order when prepending library paths

When using add_library_dir, the paths were prepended to the library
paths and ended up being reversed from their insertion order.

This causes weird behavior when using dpkg-shlibdeps -l option.

Closes: #823805
Guillem Jover пре 10 година
родитељ
комит
4497945914
3 измењених фајлова са 38 додато и 22 уклоњено
  1. 3 0
      debian/changelog
  2. 22 14
      scripts/Dpkg/Shlibs.pm
  3. 13 8
      scripts/t/Dpkg_Shlibs.t

+ 3 - 0
debian/changelog

@@ -69,6 +69,9 @@ dpkg (1.18.8) UNRELEASED; urgency=medium
       if they are the same. Closes: #745366, #827628
     - Add support for new environment variable DEB_BUILD_PATH to be able to
       control the path in the fixdebugpath feature in Dpkg::Vendor::Debian.
+    - Preserve order when prepending shared library paths in Dpkg::Shlibs.
+      This fixes the order of paths passed via dpkg-shlibdeps -l option.
+      Closes: #823805
   * Test suite:
     - Bump perlcritic ValuesAndExpressions::RequireNumberSeparators minimum
       to 99999.

+ 22 - 14
scripts/Dpkg/Shlibs.pm

@@ -46,7 +46,10 @@ use constant DEFAULT_LIBRARY_PATH =>
 use constant DEFAULT_MULTILIB_PATH =>
     qw(/lib32 /usr/lib32 /lib64 /usr/lib64);
 
-my @librarypaths;
+# Library paths set by the user.
+my @custom_librarypaths;
+# Library paths from the system.
+my @system_librarypaths;
 my $librarypaths_init;
 
 sub parse_ldso_conf {
@@ -68,8 +71,8 @@ sub parse_ldso_conf {
 	} elsif (m{^\s*/}) {
 	    s/^\s+//;
 	    my $libdir = $_;
-	    if (none { $_ eq $libdir } @librarypaths) {
-		push @librarypaths, $libdir;
+	    if (none { $_ eq $libdir } (@custom_librarypaths, @system_librarypaths)) {
+		push @system_librarypaths, $libdir;
 	    }
 	}
     }
@@ -77,18 +80,22 @@ sub parse_ldso_conf {
 }
 
 sub blank_library_paths {
-    @librarypaths = ();
+    @custom_librarypaths = ();
+    @system_librarypaths = ();
     $librarypaths_init = 1;
 }
 
 sub setup_library_paths {
-    @librarypaths = ();
+    @custom_librarypaths = ();
+    @system_librarypaths = ();
 
     # XXX: Deprecated. Update library paths with LD_LIBRARY_PATH.
     if ($ENV{LD_LIBRARY_PATH}) {
         foreach my $path (split /:/, $ENV{LD_LIBRARY_PATH}) {
             $path =~ s{/+$}{};
-            push @librarypaths, $path;
+            # XXX: This should be added to @custom_librarypaths, but as this
+            # is deprecated we do not care as the code will go away.
+            push @system_librarypaths, $path;
         }
     }
 
@@ -108,15 +115,15 @@ sub setup_library_paths {
     }
     # Define list of directories containing crossbuilt libraries.
     if ($multiarch) {
-        push @librarypaths, "/lib/$multiarch", "/usr/lib/$multiarch";
+        push @system_librarypaths, "/lib/$multiarch", "/usr/lib/$multiarch";
     }
 
-    push @librarypaths, DEFAULT_LIBRARY_PATH;
+    push @system_librarypaths, DEFAULT_LIBRARY_PATH;
 
     # Update library paths with ld.so config.
     parse_ldso_conf('/etc/ld.so.conf') if -e '/etc/ld.so.conf';
 
-    push @librarypaths, DEFAULT_MULTILIB_PATH;
+    push @system_librarypaths, DEFAULT_MULTILIB_PATH;
 
     $librarypaths_init = 1;
 }
@@ -126,13 +133,13 @@ sub add_library_dir {
 
     setup_library_paths() if not $librarypaths_init;
 
-    unshift @librarypaths, $dir;
+    push @custom_librarypaths, $dir;
 }
 
 sub get_library_paths {
     setup_library_paths() if not $librarypaths_init;
 
-    return @librarypaths;
+    return (@custom_librarypaths, @system_librarypaths);
 }
 
 # find_library ($soname, \@rpath, $format, $root)
@@ -141,10 +148,11 @@ sub find_library {
 
     setup_library_paths() if not $librarypaths_init;
 
+    my @librarypaths = (@{$rpath}, @custom_librarypaths, @system_librarypaths);
+
     $root //= '';
     $root =~ s{/+$}{};
-    my @rpath = @{$rpath};
-    foreach my $dir (@rpath, @librarypaths) {
+    foreach my $dir (@librarypaths) {
 	my $checkdir = "$root$dir";
 	# If the directory checked is a symlink, check if it doesn't
 	# resolve to another public directory (which is then the canonical
@@ -152,7 +160,7 @@ sub find_library {
 	# is /usr/lib64 -> /usr/lib on amd64.
 	if (-l $checkdir) {
 	    my $newdir = resolve_symlink($checkdir);
-	    if (any { "$root$_" eq "$newdir" } (@rpath, @librarypaths)) {
+	    if (any { "$root$_" eq "$newdir" } @librarypaths) {
 		$checkdir = $newdir;
 	    }
 	}

+ 13 - 8
scripts/t/Dpkg_Shlibs.t

@@ -34,14 +34,19 @@ my $datadir = $srcdir . '/t/Dpkg_Shlibs';
 
 my @librarypaths;
 
-Dpkg::Shlibs::add_library_dir('/test-b');
-@librarypaths = Dpkg::Shlibs::get_library_paths();
-is($librarypaths[0], '/test-b', 'add_library_dir() does not get lost');
-
-Dpkg::Shlibs::add_library_dir('/test-a');
-@librarypaths = Dpkg::Shlibs::get_library_paths();
-is_deeply([ @librarypaths[0, 1] ] , [ '/test-a', '/test-b' ],
-          'add_library_dir() prepends');
+{
+    # XXX: Keep as long as we support the deprecated LD_LIBRARY_PATH.
+    local $ENV{LD_LIBRARY_PATH} = '/test-env';
+
+    Dpkg::Shlibs::add_library_dir('/test-a');
+    @librarypaths = Dpkg::Shlibs::get_library_paths();
+    is($librarypaths[0], '/test-a', 'add_library_dir() does not get lost');
+
+    Dpkg::Shlibs::add_library_dir('/test-b');
+    @librarypaths = Dpkg::Shlibs::get_library_paths();
+    is_deeply([ @librarypaths[0, 1] ] , [ '/test-a', '/test-b' ],
+              'add_library_dir() prepends');
+}
 
 Dpkg::Shlibs::blank_library_paths();