Author: fw
Date: 2005-09-21 06:08:51 +0000 (Wed, 21 Sep 2005)
New Revision: 2062
Modified:
lib/python/security_db.py
Log:
lib/python/security_db.py (DB.calculateVulnerabilities):
Factor out testing and unstable code.
(DB._calcUnstable):
New. Mostly unchanged from the verison in calculateVulnerabilities.
(DB._calcTesting):
Rewritten from scratch. Now works on source packages. Should be
more reliable.
Modified: lib/python/security_db.py
==================================================================---
lib/python/security_db.py 2005-09-21 04:03:03 UTC (rev 2061)
+++ lib/python/security_db.py 2005-09-21 06:08:51 UTC (rev 2062)
@@ -1030,184 +1030,104 @@
for (bug_name,) in cursor.execute(
"SELECT name FROM bugs WHERE NOT not_for_us"):
- # Calculate status for unstable. Only source package
- # status is relevant here.
+ self._calcUnstable(c, bug_name)
+ self._calcTesting(c, bug_name)
- def handle_unstable():
- unstable_packages = []
- for (package,) in c.execute(
- """SELECT DISTINCT sp.name
- FROM package_notes AS n,
- source_package_status AS st, source_packages AS sp
- WHERE n.bug_name = ? AND n.urgency <>
''unimportant''
- AND n.release = ''''
- AND st.note = n.id AND st.vulnerable
- AND sp.rowid = st.package AND sp.release =
''sid''
- ORDER BY sp.name""",
- (bug_name,)):
- unstable_packages.append(package)
+ return result
- if unstable_packages:
- if len(unstable_packages) == 1:
- pkgs = ("package %s is vulnerable"
- % unstable_packages[0])
- else:
- pkgs = ("packages %s are vulnerable"
- % '',
''.join(unstable_packages))
- c.execute("""INSERT INTO bug_status
- (bug_name, release, status, reason)
- VALUES (?, ''unstable'',
''vulnerable'', ?)""",
- (bug_name, pkgs))
- else:
- c.execute("""INSERT INTO bug_status
- (bug_name, release, status, reason)
- VALUES (?, ''unstable'',
''fixed'',
- ''not known to be
vulnerable'')""",
- (bug_name,))
- handle_unstable()
+ def _calcUnstable(self, cursor, bug_name):
+ """Update bug_status with bug_name for
unstable."""
+
+ vulnerable_packages = []
+ for (package,) in cursor.execute(
+ """SELECT DISTINCT sp.name
+ FROM package_notes AS n,
+ source_package_status AS st, source_packages AS sp
+ WHERE n.bug_name = ? AND n.urgency <>
''unimportant''
+ AND n.release = ''''
+ AND st.note = n.id AND st.vulnerable
+ AND sp.rowid = st.package AND sp.release = ''sid''
+ ORDER BY sp.name""",
+ (bug_name,)):
+ vulnerable_packages.append(package)
- # The algorith below roughly proceeds as follows:
- #
- # For each package:
- # Is this package in testing/unstable? If not, exit.
- #
- # Differentiate between the following cases:
- # For all architectures with security support, the
- # package in testing is not vulnerable (fully fixed)
- #
- # For all architectures with security support, the
- # package is not vulnerable in testing or
- # testing-security, and there exists a package (on a
- # security support architecture) which is vulnerable
- # in testing (partially fixed)
- #
- # There exists an architecture with security support
- # where the package is fixed in testing, and there
- # exists a non-vulnerable architecture in testing
- # (should not happen, partially-fixed)
- #
- # Same as the preceding case, but including
- # test-security; this can actually happen
- # (partially-fixed, secure-testing is out-of-date on
- # some architectures)
- #
- # There exists an architecture with security support
- # where the package is fixed in unstable, and all
- # packages in testing are vulnerable, and the
- # package is in testing (fixed in unstable)
- #
- # For some supported architecture the package is in
- # testing, and vulnerable. It is
- #
- # The package is not in testing on any supported
- # architecture,
- #
- # At least this is the plan. The code below probably does
- # something slightly different. 8-(
+ if vulnerable_packages:
+ if len(vulnerable_packages) == 1:
+ pkgs = "package %s is vulnerable" %
vulnerable_packages[0]
+ else:
+ pkgs = ("packages %s are vulnerable"
+ % '', ''.join(vulnerable_packages))
+ cursor.execute("""INSERT INTO bug_status
+ (bug_name, release, status, reason)
+ VALUES (?, ''unstable'',
''vulnerable'', ?)""",
+ (bug_name, pkgs))
+ else:
+ cursor.execute("""INSERT INTO bug_status
+ (bug_name, release, status, reason)
+ VALUES (?, ''unstable'',
''fixed'',
+ ''not known to be
vulnerable'')""",
+ (bug_name,))
- available_archs = {}
- vulnerable_in_other = {}
- vulnerable_in_testing = {}
- fixed_in_testing = {}
- fixed_in_security = {}
+ def _calcTesting(self, cursor, bug_name):
+ """Update bug_status with bug_name for
unstable."""
- def record_archs_per_package(dict, pkg, archs):
- if not dict.has_key(pkg):
- dict[pkg] = {}
- for arch in archs.split('',''):
- dict[pkg][arch] = True
-
- for (pkg_name, release, subrelease, archs, vulnerable) \
- in c.execute(
- """SELECT DISTINCT
- p.name, p.release, p.subrelease, p.archs, vulnerable
- FROM binary_package_status AS s, binary_packages AS p
- WHERE s.bug_name = ? AND p.rowid = s.package""",
(bug_name,)):
- if not binary_packages_in_testing.has_key(pkg_name):
- continue
+ # Note that there is at most one source package per
+ # note/release/subrelease triple, but we should check that
+ # here. (A separate test is needed.)
- record_archs_per_package(available_archs, pkg_name, archs)
+ status = {'''' : {}, ''security'' : {}}
+ for (package, note, subrelease, vulnerable) in cursor.execute(
+ """SELECT DISTINCT sp.name, n.id, sp.subrelease,
+ st.vulnerable
+ FROM package_notes AS n,
+ source_package_status AS st, source_packages AS sp
+ WHERE n.bug_name = ? AND n.urgency <>
''unimportant''
+ AND st.note = n.id
+ AND sp.rowid = st.package AND sp.release = ''etch''
+ AND sp.subrelease IN ('''',
''security'')
+ ORDER BY sp.name""",
+ (bug_name,)):
+ status[subrelease][(package, note)] = vulnerable
- if release == ''etch'':
- if vulnerable:
- record_archs_per_package(vulnerable_in_testing,
- pkg_name, archs)
- else:
- if subrelease == '''':
- record_archs_per_package(fixed_in_testing,
- pkg_name, archs)
- record_archs_per_package(fixed_in_security,
- pkg_name, archs)
- elif subrelease == ''security'':
- record_archs_per_package(fixed_in_security,
- pkg_name, archs)
- elif vulnerable:
- record_archs_per_package(vulnerable_in_other,
- pkg_name, archs)
+ # Check if any packages in plain testing are vulnerable, and
+ # if all of those have been fixed in the security archive.
+ fixed_in_security = True
+ pkgs = {}
+ for ((package, note), vulnerable) in
status[''''].items():
+ if vulnerable:
+ pkgs[package] = True
+ if status[''security''].get((package, note),
True):
+ fixed_in_security = False
- def record(status, reason):
- if status <> ''vulnerable'':
- ((has_todo,),) = c.execute(
- """SELECT EXISTS (SELECT * FROM
bugs_notes
- WHERE bug_name = ? AND typ =
''TODO'')""",
- (bug_name,))
- if has_todo:
- status = ''todo''
- reason = ''see notes below''
-
- c.execute(
- """INSERT INTO bug_status
- (bug_name, release, status, reason)
- VALUES (?, ''testing'', ?,
?)""",
- (bug_name, status, reason))
+ pkgs = pkgs.keys()
+ pkgs.sort()
+ if len(pkgs) == 0:
+ if len(status[''''].keys()) == 0:
+ msg = "not known to be vulnerable"
+ else:
+ msg = "not vulnerable"
+ cursor.execute("""INSERT INTO bug_status
+ (bug_name, release, status, reason)
+ VALUES (?, ''testing'', ''fixed'',
?)""",
+ (bug_name, msg))
+ return
- if len(available_archs.keys()) == 0:
- record(''fixed'',
- ''package(s) neither in testing nor in
unstable'')
- continue
+ if len(pkgs) == 1:
+ pkgs = "package " + pkgs[0] + " is "
+ else:
+ pkgs = "packages " + ", ".join(pkgs) + "
are "
+ if fixed_in_security:
+ pkgs += "fixed in testing-security"
+ status = "partially-fixed"
+ else:
+ pkgs += "vulnerable"
+ status = "vulnerable"
- totally_unfixed_packages = []
- testing_missing_archs = {}
- security_missing_archs = {}
- for (pkg_name, archs) in vulnerable_in_other.items():
- fixed_somewhere = False
- for arch in archs.keys():
- if fixed_in_testing.get(pkg_name, {}).has_key(arch):
- fixed_somewhere = True
- else:
- testing_missing_archs[arch] = True
- if fixed_in_security.get(pkg_name, {}).has_key(arch):
- fixed_somewhere = True
- else:
- security_missing_archs[arch] = True
- if not fixed_somewhere:
- totally_unfixed_packages.append(pkg_name)
-
- if totally_unfixed_packages:
- totally_unfixed_packages.sort()
- if len(totally_unfixed_packages) == 1:
- record(''vulnerable'', ''package %s
is vulnerable''
- % totally_unfixed_packages[0])
- else:
- record(''vulnerable'', ''packages
%s are vulnerable''
- % '',
''.join(totally_unfixed_packages))
- continue
+ cursor.execute("""INSERT INTO bug_status
+ (bug_name, release, status, reason)
+ VALUES (?, ''testing'', ?, ?)""",
+ (bug_name, status, pkgs))
- if security_missing_archs.keys():
- record(''partially-fixed'',
- ''fixed via testing-security, ''
- + ''but architectures out of date: ''
- + '',
''.join(security_missing_archs.keys()))
- continue
-
- if testing_missing_archs.keys():
- record(''partially-fixed'', ''fixed in
testing-security'')
- continue
-
- record(''fixed'', ''packages are not
vulnerable'')
-
- return result
-
def getSourcePackageVersions(self, cursor, pkg):
"""A generator which returns tuples (RELEASE-LIST,
VERSION),
the available versions of the source package pkg."""