[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[SCM] Debian package checker branch, master, updated. 7f71195c6cad53edbc36f98afc68484086f0c298



The following commit has been merged in the master branch:
commit 7f71195c6cad53edbc36f98afc68484086f0c298
Author: Adam D. Barratt <adam@adam-barratt.org.uk>
Date:   Fri Jun 27 20:32:51 2008 +0100

    Enhance symbol checking support
    
      + Implement syntax and sanity checking for symbols files
        (Closes: #452216)
      + Check symbols files for dependencies that are not satisfied by
        the package itself

diff --git a/checks/shared-libs b/checks/shared-libs
index 54b70b4..9ee576a 100644
--- a/checks/shared-libs
+++ b/checks/shared-libs
@@ -57,6 +57,7 @@ my $postinst = "control/postinst";
 my $preinst = "control/preinst";
 my $prerm = "control/prerm";
 my $shlibs_control_file = "control/shlibs";
+my $symbols_control_file = "control/symbols";
 my %SONAME;
 my %INTERP;
 my %STACK;
@@ -287,6 +288,18 @@ if (open (VERSION, '<', 'fields/version')) {
     close VERSION;
     chomp $version;
 }
+my $provides = $pkg . "( = $version)";
+if (open (PROVIDES, '<', 'fields/provides')) {
+    my $line = <PROVIDES>;
+    close PROVIDES;
+    chomp $line;
+    $provides .= ", $line";
+}
+$provides = Dep::parse($provides);
+
+my %shlibs_control;
+my %symbols_control;
+
 @shlibs = grep { !m,^lib/libnss_[^.]+\.so(\.[0-9]+)$, } keys %SONAME;
 if ($#shlibs == -1) {
     # no shared libraries included in package, thus shlibs control file should
@@ -306,7 +319,6 @@ if ($#shlibs == -1) {
 	}
     } else {
 	my %shlibs_control_used;
-	my %shlibs_control;
 	my @shlibs_depends;
 	open(SHLIBS, '<', $shlibs_control_file)
 	    or fail("cannot open shlibs control file $shlibs_control_file for reading: $!");
@@ -333,13 +345,7 @@ if ($#shlibs == -1) {
 	my $shlib_name;
 	for my $shlib (@shlibs) {
 	    $shlib_name = $SONAME{$shlib};
-	    # libfoo.so.X.X
-	    if ($shlib_name =~ m/(.+)\.so\.(.*)$/) {
-		$shlib_name = "$1 $2";
-	    # libfoo-X.X.so
-	    } elsif ($shlib_name =~ m/(.+)\-(\w[\w\.]*)\.so$/) {
-		$shlib_name = "$1 $2";
-	    }
+	    $shlib_name = format_soname($shlib_name);
 	    $shlibs_control_used{$shlib_name} = 1;
 	    $shlibs_control_used{"udeb: ".$shlib_name} = 1;
 	    unless (exists $shlibs_control{$shlib_name}) {
@@ -361,14 +367,6 @@ if ($#shlibs == -1) {
 	#
 	# Deduplicate the list of dependencies before warning so that we don't
 	# dupliate warnings.
-	my $provides = $pkg . "( = $version)";
-	if (open (PROVIDES, '<', 'fields/provides')) {
-	    my $line = <PROVIDES>;
-	    close PROVIDES;
-	    chomp $line;
-	    $provides .= ", $line";
-	}
-	$provides = Dep::parse($provides);
 	my %seen;
 	@shlibs_depends = grep { !$seen{$_}++ } @shlibs_depends;
 	for my $depend (@shlibs_depends) {
@@ -380,21 +378,99 @@ if ($#shlibs == -1) {
 }
 
 # 5th step: check symbols control file
-if (open(IN, '<', 'control/symbols')) {
+if ($#shlibs == -1) {
+    # no shared libraries included in package, thus symbols control file should
+    # not be present
+    if (-f $symbols_control_file) {
+        tag "pkg-has-symbols-control-file-but-no-shared-libs", "";
+    }
+} elsif (not -f $symbols_control_file) {
+    if ($type ne 'udeb') {
+	for my $shlib (@shlibs) {
+	    # skip it if it's not a public shared library
+	    next unless $ldconfig_dirs->known(dirname($shlib));
+	    tag "no-symbols-control-file", "$shlib";
+	}
+    }
+} elsif (open(IN, '<', $symbols_control_file)) {
     my $version_wo_rev = $version;
     $version_wo_rev =~ s/^(.+)-([^-]+)$/$1/;
     my ($full_version_count, $full_version_sym) = (0, undef);
     my ($debian_revision_count, $debian_revision_sym) = (0, undef);
+    my ($soname, $dep_package, $dep);
+    my %symbols_control_used;
+    my @symbols_depends;
+    my $dep_templates = 0;
+    my $meta_info_seen = 0;
+
     while (<IN>) {
-	next if not /^\s+(\S+)\s(\S+)(?:\s(\d+))?/;
-	my ($sym, $v, $dep_order) = ($1, $2, $3);
-	if (($v eq $version) and ($version =~ /-/)) {
-	    $full_version_sym ||= $sym;
-	    $full_version_count++;
-	}
-	if (($v =~ /-/) and (not $v =~ /~$/) and ($v ne $version_wo_rev)) {
-	    $debian_revision_sym ||= $sym;
-	    $debian_revision_count++;
+	chomp;
+	next if m/^\s*$/ or /^#/;
+
+	if (m/^([^\s|*]\S+)\s(\S+)(?:\s(\S+))?/) {
+	    # soname, main dependency template
+
+	    ($soname, $dep_package, $dep) = ($1, $2, $3);
+	    $dep ||= '';
+	    $soname = format_soname($soname);
+
+	    if ($symbols_control{$soname}) {
+		tag "duplicate-entry-in-symbols-control-file", $soname;
+	    } else {
+		$symbols_control{$soname} = 1;
+		push @symbols_depends, $dep_package . ' ' . $dep;
+	    }
+
+	    $dep_templates = 0;
+	    $meta_info_seen = 0;
+	} elsif (m/^\|\s+(\S+)\s(\S+(\s\S+)?)$/) {
+	    # alternative dependency template
+
+	    if ($meta_info_seen or not defined $soname) {
+		tag "syntax-error-in-symbols-file", $.;
+	    }
+
+	    ($dep_package, $dep) = ($1, $2);
+	    push @symbols_depends, $dep_package . ' ' . $dep;
+	    $dep_templates++;
+	} elsif (m/^\*\s(\S+):\s(\S+)/) {
+	    # meta-information
+
+	    # This should probably be in a hash, but there's
+	    # only one supported value currently
+	    tag "unknown-meta-field-in-symbols-file", "$1, line $."
+		unless $1 eq 'Build-Depends-Package';
+	    tag "syntax-error-in-symbols-file", $.
+		if $dep_templates > 0;
+
+	    $meta_info_seen = 1;
+	} elsif (m/^\s+(\S+)\s(\S+)(?:\s(\S+(\s\S+)?))?$/) {
+	    # Symbol definition
+
+	    tag "syntax-error-in-symbols-file", $.
+		unless defined $soname;
+
+	    my ($sym, $v, $dep_order) = ($1, $2, $3);
+	    $dep_order ||= '';
+
+	    if (($v eq $version) and ($version =~ /-/)) {
+		$full_version_sym ||= $sym;
+		$full_version_count++;
+	    }
+	    if (($v =~ /-/) and (not $v =~ /~$/) and ($v ne $version_wo_rev)) {
+		$debian_revision_sym ||= $sym;
+		$debian_revision_count++;
+	    }
+
+	    if (length $dep_order) {
+		if ($dep_order !~ /^\d+$/ or $dep_order > $dep_templates) {
+		    tag "invalid-template-id-in-symbols-file", $.;
+		}
+	    }
+	} else {
+	    # Unparseable line
+
+	    tag "syntax-error-in-symbols-file", $.;
 	}
     }
     close IN;
@@ -405,7 +481,7 @@ if (open(IN, '<', 'control/symbols')) {
 	    $others = " and $full_version_count others";
 	}
 	tag "symbols-file-contains-current-version-with-debian-revision",
-	    "on symbol $full_version_sym$others"
+	    "on symbol $full_version_sym$others";
     }
     if ($debian_revision_count) {
 	$debian_revision_count--;
@@ -416,8 +492,47 @@ if (open(IN, '<', 'control/symbols')) {
 	tag "symbols-file-contains-debian-revision",
 	    "on symbol $debian_revision_sym$others";
     }
+    my $shlib_name;
+    for my $shlib (@shlibs) {
+	$shlib_name = $SONAME{$shlib};
+	$shlib_name = format_soname($shlib_name);
+	$symbols_control_used{$shlib_name} = 1;
+	$symbols_control_used{"udeb: ".$shlib_name} = 1;
+	unless (exists $symbols_control{$shlib_name}) {
+	    # skip it if it's not a public shared library
+	    next unless $ldconfig_dirs->known(dirname($shlib));
+	    tag "shlib-missing-in-symbols-control-file", $shlib_name, 'for', $shlib;
+	}
+    }
+    for $shlib_name (keys %symbols_control) {
+	tag "unused-shlib-entry-in-symbols-control-file", $shlib_name
+	    unless $symbols_control_used{$shlib_name};
+    }
+
+    # Check that all of the packages listed as dependencies in the symbols
+    # file are satisfied by the current package or its Provides.
+    # Normally, packages should only declare dependencies in their symbols
+    # files that they themselves can satisfy.
+    #
+    # Deduplicate the list of dependencies before warning so that we don't
+    # dupliate warnings.
+    my %seen;
+    @symbols_depends = grep { !$seen{$_}++ } @symbols_depends;
+    for my $depend (@symbols_depends) {
+	unless (Dep::implies($provides, Dep::parse($depend))) {
+	    tag "symbols-declares-dependency-on-other-package", $depend;
+	}
+    } 
 }
 
+# Compare the contents of the shlibs and symbols control files
+if (keys %shlibs_control and keys %symbols_control) {
+    for my $key (keys %symbols_control) {
+	unless (exists $shlibs_control{$key}) {
+	    tag "symbols-declared-but-not-shlib", $key;
+	}
+    }
+}
 
 # 6th step: check pre- and post- control files
 if (-f $preinst) {
@@ -491,6 +606,20 @@ sub abs_path {
     return $path;
 }
 
+sub format_soname {
+    my $soname = shift;
+
+    # libfoo.so.X.X
+    if ($soname =~ m/(.+)\.so\.(.*)$/) {
+	$soname = "$1 $2";
+    # libfoo-X.X.so
+    } elsif ($soname =~ m/(.+)\-(\w[\w\.]*)\.so$/) {
+	$soname = "$1 $2";
+    }
+
+    return $soname
+}
+
 1;
 
 # Local Variables:
diff --git a/checks/shared-libs.desc b/checks/shared-libs.desc
index d58919e..df27cb7 100644
--- a/checks/shared-libs.desc
+++ b/checks/shared-libs.desc
@@ -230,3 +230,77 @@ Info: Debian revisions should be stripped from versions in symbols files.
  be stripped because the symbol really appearead between two specific
  Debian revisions, you should postfix the version with a single "~"
  (example: 1.0-3~ if the symbol appeared in 1.0-3).
+
+Tag: syntax-error-in-symbols-file
+Type: error
+Info: The symbols file contains an entry that does not follow the syntax
+ rules for symbols files.
+ .
+ This may be due to the entry appearing out of sequence.
+Ref: deb-symbols(5)
+
+Tag: duplicate-entry-in-symbols-control-file
+Type: error
+Info: The symbols control file contains a duplicate entry.
+
+Tag: no-symbols-control-file
+Type: info
+Info: Although the package includes a shared library, the package does not
+ have a symbols control file.
+
+Tag: pkg-has-symbols-control-file-but-no-shared-libs
+Type: error
+Info: Although the package does not include any shared libraries, it does
+ have a symbols control file. If you did include a shared library, check that
+ the SONAME of the library is set and that it matches the contents of the
+ symbols file.
+ .
+ SONAMEs are set with something like <tt>gcc -Wl,-soname,libfoo.so.0</tt>,
+ where 0 is the major version of the library. If your package uses libtool,
+ then libtool invoked with the right options should be doing this.
+
+Tag: shlib-missing-in-symbols-control-file
+Type: warning
+Info: The package contains a shared library that is not listed in the
+ symbols control file. This may not be a problem if, for example,
+ the library is a C++ library.
+
+Tag: unused-shlib-entry-in-symbols-control-file
+Type: warning
+Info: The symbols control file contains an entry for a shared library that
+ is not installed by this package.
+
+Tag: symbols-declares-dependency-on-other-package
+Type: warning
+Info: This package declares in its symbols control file a dependency on
+ some other package (and not one listed in the Provides of this package).
+ .
+ Packages should normally only list in their symbols control file the
+ shared libraries included in that package, and therefore the dependencies
+ listed there should normally be satisfied by either the package itself or
+ one of its Provides.
+ .
+ In unusual circumstances where it's necessary to declare more complex
+ dependencies in the symbols control file, please add a lintian override
+ for this warning.
+Ref: policy 8.6
+
+Tag: invalid-template-id-in-symbols-file
+Type: error
+Info: The symbol definition refers to an alternative dependency template
+ which is not defined for the library containing the symbol.
+ .
+ The first alternative dependency template for a library the id number
+ of 1, with the ids of subsequent alternative templates increasing in
+ sequence.
+
+Tag: unknown-meta-field-in-symbols-file
+Type: error
+Info: The symbols control file contains an unknown meta-information field.
+ .
+ A list of currently supported fields may be found in deb-control(5).
+
+Tag: symbols-declared-but-not-shlib
+Type: error
+Info: The symbols control file contains dependency and symbol information
+ for a shared library which is not listed in the shlibs control file.
diff --git a/debian/changelog b/debian/changelog
index 0c75909..728fd9a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -33,6 +33,11 @@ lintian (1.24.2) unstable; urgency=low
       Patch by Adam D. Barratt.
     + [ADB] Update bashism regexes to add new checks, improve performance
       and reduce false positives.
+  * checks/shared-libs{,.desc}:
+    + [ADB] Implement syntax and sanity checking for symbols files
+      (Closes: #452216)
+    + [ADB] Check symbols files for dependencies that are not satisfied by
+      the package itself (Closes: #461575)
   * checks/watch-file{,.desc}:
     + [FL] Check for more Debian specific strings in version
       number.  Issue an info tag if the watch file uses
diff --git a/testset/debug/debian/_symbols b/testset/debug/debian/_symbols
new file mode 100644
index 0000000..a91ce05
--- /dev/null
+++ b/testset/debug/debian/_symbols
@@ -0,0 +1,22 @@
+  This line should flag a syntax error
+# but this one shouldn't
+| although this one should, but for a different reason
+ and so should this
+
+libhello.so.0 libhello0 #MINVER#
+| libhello0c2 (>= 1.2)
+| hello-dbg
+ hello@Base 1.0
+* Build-Dep-Foo: bar
+ hello2@Base 2.0 3
+ hello3@Base 2.0 1
+ hello3@Base 2.0 A
+ dummy
+
+libhello.so.2 libhello2 #MINVER#
+* Build-Depends-Package: libbar
+| libhello2 (>= 1:2.3)
+ hello@Base 2.0
+
+libhello.so.0 libhello0 #MINVER#
+ duplicate@Base 1.0
diff --git a/testset/debug/debian/rules b/testset/debug/debian/rules
index a1327fe..a40c380 100755
--- a/testset/debug/debian/rules
+++ b/testset/debug/debian/rules
@@ -65,6 +65,21 @@ binary-arch: build-stamp install
 	dh_makeshlibs -X debug
 	dh_installdeb
 	dh_shlibdeps -X debug
+
+	# We do this by hand as otherwise dpkg-gensymbols
+	# will error due to the broken symbols file
+	# and abort the build; similarly the file in
+	# the source tree is _symbols so that dpkg
+	# doesn't attempt to sanity check it
+	install -d $(CURDIR)/debian/libhello0/DEBIAN
+	install -m 644 $(CURDIR)/debian/_symbols \
+	    $(CURDIR)/debian/libhello0/DEBIAN/symbols
+	# hello doesn't contain any shlibs, but we
+	# make it contain a symbols file
+	install -d $(CURDIR)/debian/hello/DEBIAN
+	install -m 644 $(CURDIR)/debian/_symbols \
+	    $(CURDIR)/debian/hello/DEBIAN/symbols
+
 	dh_gencontrol
 	dh_md5sums
 	dh_builddeb
diff --git a/testset/tags.debug b/testset/tags.debug
index df79fac..134cfcb 100644
--- a/testset/tags.debug
+++ b/testset/tags.debug
@@ -1,10 +1,24 @@
 E: debug source: build-depends-indep-without-arch-indep
 E: debug source: version-substvar-for-external-package libhello0-dbg -> libhello
+E: hello: pkg-has-symbols-control-file-but-no-shared-libs
 E: hello: statically-linked-binary ./usr/bin/hello.dbg
 E: hello: unstripped-binary-or-object ./usr/bin/hello.dbg
 E: libhello0-dbg: binary-with-bad-dynamic-table ./usr/lib/libhello.so.dbg
 E: libhello0-dbg: missing-dependency-on-libc needed by ./usr/lib/debug/lib/libhello.so.0.0 and 1 others
 E: libhello0-dbg: sharedobject-in-library-directory-missing-soname usr/lib/libhello.so.dbg
+E: libhello0: duplicate-entry-in-symbols-control-file libhello 0
+E: libhello0: invalid-template-id-in-symbols-file 11
+E: libhello0: invalid-template-id-in-symbols-file 13
+E: libhello0: invalid-template-id-in-symbols-file 4
+E: libhello0: symbols-declared-but-not-shlib libhello 2
+E: libhello0: syntax-error-in-symbols-file 1
+E: libhello0: syntax-error-in-symbols-file 10
+E: libhello0: syntax-error-in-symbols-file 14
+E: libhello0: syntax-error-in-symbols-file 18
+E: libhello0: syntax-error-in-symbols-file 3
+E: libhello0: syntax-error-in-symbols-file 4
+E: libhello0: syntax-error-in-symbols-file 8
+E: libhello0: unknown-meta-field-in-symbols-file Build-Dep-Foo, line 10
 W: debug source: ancient-standards-version 3.7.0 (current is 3.8.0)
 W: debug source: changelog-should-not-mention-nmu
 W: debug source: debhelper-script-needs-versioned-build-depends dh_icons (>= 5.0.51~)
@@ -14,3 +28,7 @@ W: hello: binary-without-manpage usr/bin/hello.dbg
 W: libhello0-dbg: dbg-package-missing-depends libhello0
 W: libhello0-dbg: debug-file-should-use-detached-symbols ./usr/lib/debug/lib/libhello.so.0.0
 W: libhello0-dbg: shared-lib-without-dependency-information ./usr/lib/libhello.so.dbg
+W: libhello0: symbols-declares-dependency-on-other-package libhello0c2 (>= 1.2)
+W: libhello0: symbols-declares-dependency-on-other-package libhello2 #MINVER#
+W: libhello0: symbols-declares-dependency-on-other-package libhello2 (>= 1:2.3)
+W: libhello0: unused-shlib-entry-in-symbols-control-file libhello 2

-- 
Debian package checker


Reply to: