Package: lintian
Version: 2.134.0
Severity: minor
Tags: patch
When a changelog entry body mentions a 4-component Standards-Version
(e.g. "Bump Standards-Version to 4.7.4.1, no changes required."),
lintian incorrectly fires the standards-version-inconsistent hint with
a garbled comparison. Debian Policy §4.6.1 explicitly permits the
4-component form.
Reproducer
----------
debian/control:
Standards-Version: 4.7.4.1
debian/changelog entry body:
* Bump Standards-Version to 4.7.4.1, no changes required.
lintian output (2.134.0):
W: <source>: standards-version-inconsistent 4.7.4 != 7.4.1
The version "7.4.1" does not appear anywhere in the package or on the
system. It is an artefact of the regex in
Fields/StandardsVersion.pm extracting the last three-component
substring of "4.7.4.1", which is "7.4.1".
Root cause
----------
File: /usr/share/lintian/lib/Lintian/Check/Fields/StandardsVersion.pm
Lintian version: 2.134.0
Lines 68-71 correctly normalize the control-field version to three
components by taking the first three elements of @compliance_components
and joining them with dots ("4.7.4.1" becomes "4.7.4" in
$compliance_normalized).
Lines 100-102 extract the version string mentioned in the changelog:
if ($changes
=~ /(?:standards[
-]?version|\bs-v:?\s).*\b(\d+\.\d+\.\d+)\b(?!.*\b\d+\.\d+\.\d+\b)/i
) {
The `.*` is greedy and the negative lookahead forces it to settle on
the *last* three-component substring in the line. In the string
"4.7.4.1" there are two overlapping three-component matches: "4.7.4"
(at position 0) and "7.4.1" (starting between the first and second
dots). The greedy match picks "7.4.1", so $changelog_standard (line
103) is set to "7.4.1" instead of "4.7.4".
The subsequent comparison on line 107 ("4.7.4" ne "7.4.1") fires the
hint.
Suggested fix
-------------
Make the match non-greedy and optionally capture a fourth component so
the comparison works correctly for both 3- and 4-component versions:
# Before (line 101):
=~ /(?:standards[
-]?version|\bs-v:?\s).*\b(\d+\.\d+\.\d+)\b(?!.*\b\d+\.\d+\.\d+\b)/i
# After:
=~ /(?:standards[ -]?version|\bs-v:?\s).*?\b(\d+\.\d+\.\d+(?:\.\d+)?)\b/i
`.*?` stops at the first version string after the keyword rather than
the last. The optional `(?:\.\d+)?` captures a fourth component when
present, so $changelog_standard becomes "4.7.4.1"; the existing
normalisation on lines 68-71 already strips the fourth component from
$compliance_normalized, so the ne comparison then correctly handles
both 3 and 4 component mentions in the changelog.
Policy reference
----------------
Debian Policy 5.6.11:
"Thus only the first three components of the policy version are
significant in the Standards-Version control field, and so either
these three components or all four components may be specified."
Workaround
----------
Use the 3-component form ("4.7.4") in both debian/control and in
changelog entry text. This avoids the false positive and is the form
Policy cites as the primary reference.
Regards,
James