[Git][security-tracker-team/security-tracker][master] 11 commits: lib: change internUrgency not to return None
Emilio Pozuelo Monfort (@pochu)
pochu at debian.org
Fri Aug 7 15:51:18 BST 2026
Emilio Pozuelo Monfort pushed to branch master at Debian Security Tracker / security-tracker
Commits:
832e5521 by Helmut Grohne at 2026-08-07T08:39:32+02:00
lib: change internUrgency not to return None
A number of callers of internUrgency are not prepared to handle its None
return value. Rather than fix all the callers, make it raise an
exception and adapt the one place that wants to handle it.
- - - - -
299395b2 by Helmut Grohne at 2026-08-07T08:39:32+02:00
lib: change internRelease not to return None
A number of callers of internRelease are not prepared to handle its None
return value. Rather than fix all the callers, make it raise an
exception.
- - - - -
5fc88e8e by Helmut Grohne at 2026-08-07T08:39:32+02:00
web tracker: delete method pre_dispatch
None of the implementations is non-trivial, but the more striking issue
is that their argument count varies. Rather than figure out, what is
right, dispose this unused mechanism.
- - - - -
c33e857c by Helmut Grohne at 2026-08-07T08:39:32+02:00
delete test of isKernOnly
Fixes: efd6f70f4aca ("Remove unused methods")
- - - - -
611a6f09 by Helmut Grohne at 2026-08-07T08:40:13+02:00
security_db.py: use sets
Some of this code predates the introduction of the set type to Python
and uses dicts with True values instead. We can now convert this to
proper sets. More importantly, this helps avoid variable type changes.
The list conversion can be deferred.
- - - - -
0b09d8e2 by Helmut Grohne at 2026-08-07T08:40:15+02:00
security_db.py: rewrite mergeLists using sets
Aside from being faster, this avoids changing the type of the result
variable.
- - - - -
e9c773c7 by Helmut Grohne at 2026-08-07T08:40:15+02:00
python: avoid more variable type changes
If we ever want to head into type checking, the type of value stored in
a variable should not change. Thus rename affected assignments or elide
them entirely.
- - - - -
6e5b6e82 by Helmut Grohne at 2026-08-07T08:40:15+02:00
tracker_service.py: narrow implied type of filters attribute
The lookup in params may return None in principle. This influences type
deduction and filters is assumed to be able to hold None, but the next
line changes that. In combining them, the deduced type of filters
becomes narrower.
- - - - -
77f14a6d by Helmut Grohne at 2026-08-07T08:40:15+02:00
tracker_service.py: don't pass None via body_attribs
While a None value might be acceptable there, it is discarded anyway.
Rather than supporting that use case, simply avoid passing it.
- - - - -
53e84bf6 by Helmut Grohne at 2026-08-07T08:40:15+02:00
tracker_service.py: explicitly cast hide_check to bool
When we pass it to getTODOs a real bool is expected, so convert the
thing that might be a list early.
- - - - -
c0245516 by Emilio Pozuelo Monfort at 2026-08-07T14:51:13+00:00
Merge branch 'helmutg/type-improvements' into 'master'
lib: tweak code to make it easier consumable by type checkers
See merge request security-tracker-team/security-tracker!314
- - - - -
5 changed files:
- bin/tracker_service.py
- lib/python/bugs.py
- lib/python/debian_support.py
- lib/python/security_db.py
- lib/python/web_support.py
Changes:
=====================================
bin/tracker_service.py
=====================================
@@ -45,9 +45,9 @@ class BugFilter:
self.params = {}
for (prop, desc, field) in self.action_list:
self.params[prop] = int(params.get(prop, (0,))[0])
- self.filters=params.get('filter')
- if not self.filters:
- self.filters=['high_urgency', 'medium_urgency', 'low_urgency', 'unassigned_urgency']
+ self.filters = (
+ params.get('filter') or ['high_urgency', 'medium_urgency', 'low_urgency', 'unassigned_urgency']
+ )
def actions(self, url):
"""Returns a HTML snippet which can be used to change the filter."""
@@ -926,7 +926,7 @@ checker to find out why they have not entered testing yet."""),
"Remote", ""))])
def page_status_todo(self, path, params, url):
- hide_check = params.get('hide_check', False)
+ hide_check = bool(params.get('hide_check', False))
if hide_check:
flags = A(url.updateParamsDict({'hide_check' : None}),
'Show "check" TODOs')
@@ -1180,13 +1180,9 @@ not unimportant."""),
def gen():
for (rel, subrel, archive, sources, archs) \
in self.db.availableReleases():
- if sources:
- sources = 'yes'
- else:
- sources = 'no'
if 'source' in archs:
archs.remove('source')
- yield rel, subrel, archive, sources, make_list(archs)
+ yield rel, subrel, archive, "yes" if sources else "no" , make_list(archs)
return self.create_page(
url, "Available releases",
[P("""The security issue database is checked against
@@ -1292,17 +1288,16 @@ Debian bug number.'''),
"Source"),
" ", A(url.absolute("https://salsa.debian.org/security-tracker-team/security-tracker"), "(Git)"),
)))
+ body_attribs = {}
if search_in_page:
- on_load = "selectSearch()"
- else:
- on_load = None
+ body_attribs["onload"] = "selectSearch()"
head_contents = compose(
LINK(' ', href=url.scriptRelative("style.css")),
SCRIPT(' ', src=url.scriptRelative("script.js")),
).toHTML()
return HTMLResult(self.add_title(title, body,
head_contents=head_contents,
- body_attribs={'onload': on_load}),
+ body_attribs=body_attribs),
doctype=self.html_dtd(),
status=status)
@@ -1530,8 +1525,5 @@ Debian bug number.'''),
def make_dangerous(self, contents):
return SPAN(contents, _class="dangerous")
- def pre_dispatch(self):
- pass
-
if __name__ == "__main__":
TrackerService(socket_name, db_name).run()
=====================================
lib/python/bugs.py
=====================================
@@ -31,10 +31,10 @@ def listUrgencies():
Urgency.urgencies = urgencies
return urgencies
def internUrgency(name, urgencies=listUrgencies()):
- if name in urgencies:
+ try:
return urgencies[name]
- else:
- return None
+ except KeyError as err:
+ raise ValueError("invalid urgency") from err
del listUrgencies
def to_integer(expr):
@@ -63,13 +63,9 @@ class PackageNote:
else:
if isinstance(release, str):
release = debian_support.internRelease(release)
- if release is None:
- raise ValueError("invalid release")
self.release = release
if isinstance(urgency, str):
urgency = internUrgency(urgency)
- if urgency is None:
- raise ValueError("invalid urgency")
self.urgency = urgency
self.bugs = []
self.package_kind = "unknown"
@@ -144,10 +140,11 @@ class PackageNoteParsed(PackageNote):
urgency = 'not yet assigned'
if notes is not None:
for n in self.re_notes_split.split(notes):
- u = internUrgency(n)
- if u:
- urgency = u
+ try:
+ urgency = internUrgency(n)
continue
+ except ValueError:
+ pass
if n == 'bug filed':
continue
@@ -172,10 +169,7 @@ class PackageNoteNoDSA:
else:
assert isinstance(reason, str)
self.package = package
- release = debian_support.internRelease(release)
- if release is None:
- raise ValueError("invalid release")
- self.release = release
+ self.release = debian_support.internRelease(release)
self.comment = comment
self.reason = reason
=====================================
lib/python/debian_support.py
=====================================
@@ -218,10 +218,10 @@ def listReleases():
Release.releases = releases
return releases
def internRelease(name, releases=listReleases()):
- if name in releases:
+ try:
return releases[name]
- else:
- return None
+ except KeyError as err:
+ raise ValueError("invalid release") from err
del listReleases
def readLinesSHA1(lines):
=====================================
lib/python/security_db.py
=====================================
@@ -83,14 +83,7 @@ def mergeLists(a, b):
b = []
else:
b = b.split(',')
- result = {}
- for x in a:
- result[x] = 1
- for x in b:
- result[x] = 1
- result = list(result.keys())
- result.sort()
- return result
+ return sorted(set(a).union(b))
class NVDEntry:
"""A class for an entry in the nvd_data table.
@@ -165,7 +158,7 @@ def getBugsForSourcePackage(cursor, pkg):
# Restrict to regular releases excluding e.g. backports.
release_names = tuple(debian_support.Release.releases)
- data = itertools.starmap(
+ data_iter = itertools.starmap(
BugsForSourcePackage_internal,
cursor.execute(
BugsForSourcePackage_query.replace(
@@ -178,7 +171,7 @@ def getBugsForSourcePackage(cursor, pkg):
all_bugs = []
version_key = functools.cmp_to_key(version_compare)
# Group by bug name.
- for bug_name, data in itertools.groupby(data,
+ for bug_name, data in itertools.groupby(data_iter,
lambda row: row.bug_name):
description = None
open_seen = False
@@ -873,7 +866,7 @@ class DB:
# stores aggregated data, and there is no efficient way to
# handle updates of the records related to a single file.
- packages = {}
+ packages = defaultdict(set)
unchanged = True
for filename in filenames:
match = re_packages.match(filename)
@@ -894,10 +887,7 @@ class DB:
% (arch, name))
key = (name, release, subrelease, archive, version,
source, source_version)
- if key in packages:
- packages[key][arch] = 1
- else:
- packages[key] = {arch : 1}
+ packages[key].add(arch)
if unchanged:
if self.verbose:
@@ -909,18 +899,12 @@ class DB:
cursor.execute("DELETE FROM binary_packages")
self._clearVersions(cursor)
- l = list(packages.keys())
-
- if len(l) == 0:
+ if len(packages) == 0:
raise ValueError("no binary packages found")
- l.sort()
def gen():
- for key in l:
- archs = list(packages[key].keys())
- archs.sort()
- archs = ','.join(archs)
- yield key + (archs,)
+ for key, archs in sorted(packages.items()):
+ yield key + (",".join(sorted(archs)),)
if self.verbose:
print(" storing binary package data")
@@ -1510,28 +1494,21 @@ class DB:
# 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
- unfixed_pkgs = {}
- undet_pkgs = {}
- unimp_pkgs = {}
+ unfixed_pkgs = set()
+ undet_pkgs = set()
+ unimp_pkgs = set()
for ((package, note), (vulnerable, urgency)) in status[''].items():
if vulnerable == Vulnerable.AFFECTED:
if urgency == 'unimportant':
- unimp_pkgs[package] = True
+ unimp_pkgs.add(package)
else:
- unfixed_pkgs[package] = True
+ unfixed_pkgs.add(package)
if status['security'].get((package, note), True):
fixed_in_security = False
elif status['lts'].get((package, note), True):
fixed_in_security = False
elif vulnerable == Vulnerable.UNDETERMINED:
- undet_pkgs[package] = True
-
- unfixed_pkgs = list(unfixed_pkgs.keys())
- unfixed_pkgs.sort()
- undet_pkgs = list(undet_pkgs.keys())
- undet_pkgs.sort()
- unimp_pkgs = list(unimp_pkgs.keys())
- unimp_pkgs.sort()
+ undet_pkgs.add(package)
pkgs = ""
result = "undetermined"
@@ -1543,9 +1520,9 @@ class DB:
result = "fixed"
if len(unfixed_pkgs) > 0:
if len(unfixed_pkgs) == 1:
- pkgs += "package " + unfixed_pkgs[0] + " is "
+ pkgs += "package " + next(iter(unfixed_pkgs)) + " is "
else:
- pkgs += "packages " + ", ".join(unfixed_pkgs) + " are "
+ pkgs += "packages " + ", ".join(sorted(unfixed_pkgs)) + " are "
if fixed_in_security:
pkgs = "%sfixed in %s-security. " % (pkgs, suite)
if suite == "stable":
@@ -1557,15 +1534,15 @@ class DB:
result = "vulnerable"
if len(undet_pkgs) > 0:
if len(undet_pkgs) == 1:
- pkgs += "package " + undet_pkgs[0] + " may be vulnerable but needs to be checked."
+ pkgs += "package " + next(iter(undet_pkgs)) + " may be vulnerable but needs to be checked."
else:
- pkgs += "packages " + ", ".join(undet_pkgs) + " may be vulnerable but need to be checked."
+ pkgs += "packages " + ", ".join(sorted(undet_pkgs)) + " may be vulnerable but need to be checked."
if len(unimp_pkgs) > 0 and len(undet_pkgs) == 0 and len(unfixed_pkgs) == 0:
result = "fixed"
if len(unimp_pkgs) == 1:
- pkgs = "package %s is vulnerable; however, the security impact is unimportant." % unimp_pkgs[0]
+ pkgs = "package %s is vulnerable; however, the security impact is unimportant." % next(iter(unimp_pkgs))
else:
- pkgs = "packages %s are vulnerable; however, the security impact is unimportant." % (', '.join(unimp_pkgs))
+ pkgs = "packages %s are vulnerable; however, the security impact is unimportant." % (', '.join(sorted(unimp_pkgs)))
cursor.execute("""INSERT INTO bug_status
(bug_name, release, status, reason)
@@ -1674,9 +1651,9 @@ class DB:
kind, urgency_to_flag[urgency], remote,
fix_available,
package, fixed_version, description))
- result = zlib.compress(''.join(result).encode('utf-8'), 9)
+ compressed = zlib.compress(''.join(result).encode('utf-8'), 9)
- self.storeExport('debsecan/release/' + release, 'application/octet-stream', result)
+ self.storeExport('debsecan/release/' + release, 'application/octet-stream', compressed)
c.execute("DROP TABLE vulnlist")
@@ -1720,7 +1697,7 @@ class DB:
'not yet assigned' : ' '}
vuln_list = []
- source_packages = {}
+ source_packages = set()
def fill_vuln_list(source_packages=source_packages):
for (bug, package) in list(c.execute(
"""SELECT DISTINCT bug_name, package
@@ -1741,7 +1718,7 @@ class DB:
unstable_fixed = ''
total_urgency = ''
- other_versions = {}
+ other_versions = set()
is_binary = False
is_unknown = False
fixed_releases = {}
@@ -1764,7 +1741,7 @@ class DB:
if kind == 'binary':
is_binary = True
elif kind == 'source':
- source_packages[package] = True
+ source_packages.add(package)
else:
is_unknown = True
@@ -1793,7 +1770,7 @@ class DB:
if v is None:
continue
if debian_support.Version(v) >= v_ref:
- other_versions[v] = True
+ other_versions.add(v)
# The second part of this SELECT statement
# covers binary-only NMUs.
@@ -1805,7 +1782,7 @@ class DB:
AND release = ?2 AND subrelease IN ('', 'security', 'lts')""",
(package, release)):
if debian_support.Version(v) >= v_ref:
- other_versions[v] = True
+ other_versions.add(v)
if not total_urgency:
total_urgency = 'unknown'
@@ -1827,9 +1804,7 @@ class DB:
elif is_unknown:
bs_flag = ' '
- other_versions = list(other_versions.keys())
- other_versions.sort()
- other_versions = ' '.join(other_versions)
+ other_versions_str = ' '.join(sorted(other_versions))
vuln_list.append(("%s,%d,%c%c%c"
% (package, bug_to_index[bug],
@@ -1837,14 +1812,12 @@ class DB:
bug_to_remote_flag[bug]),
fixed_releases.keys(),
",%s,%s"
- % (unstable_fixed, other_versions)))
+ % (unstable_fixed, other_versions_str)))
fill_vuln_list()
- source_packages = list(source_packages.keys())
- source_packages.sort()
def store_value(name, value):
- value = zlib.compress(value.encode('utf-8'), 9)
- self.storeExport('debsecan/' + name, 'application/octet-stream', value)
+ compressed = zlib.compress(value.encode('utf-8'), 9)
+ self.storeExport('debsecan/' + name, 'application/octet-stream', compressed)
def gen_release(release):
result = result_start[:]
@@ -1857,7 +1830,7 @@ class DB:
result.append(prefix + fixed + suffix)
result.append('')
- for sp in source_packages:
+ for sp in sorted(source_packages):
bp_list = []
for (bp,) in c.execute("""SELECT name FROM binary_packages
WHERE source = ? AND release = ? AND subrelease = ''
@@ -1876,7 +1849,7 @@ class DB:
gen_release(release)
result = result_start
- for (prefix, release, suffix) in vuln_list:
+ for (prefix, releases, suffix) in vuln_list:
result.append(prefix + ' ' + suffix)
result.append('')
result.append('')
@@ -2136,8 +2109,8 @@ class DB:
RELEASE-LIST, VERSION, VULNERABLE-FLAG) of source packages
which are related to the given bug."""
- releases = config.get_supported_releases()
- values = [bug] + releases
+ supported_releases = config.get_supported_releases()
+ values = [bug] + supported_releases
for (package, releases, version, vulnerable_int) in cursor.execute(
"""SELECT package, string_list(release), version, vulnerable
@@ -2146,7 +2119,7 @@ class DB:
p.version AS version, s.vulnerable AS vulnerable
FROM source_package_status AS s, source_packages AS p
WHERE s.bug_name = ? AND p.rowid = s.package
- AND release in (""" + ",".join("?" * len(releases)) + """))
+ AND release in (""" + ",".join("?" * len(supported_releases)) + """))
GROUP BY package, version, vulnerable
ORDER BY package, releasepart_to_number(release), subreleasepart_to_number(release), version COLLATE version""",
values):
@@ -2458,7 +2431,5 @@ def test():
else:
assert False
- assert bugs.BugFromDB(cursor, 'DSA-311').isKernelOnly()
-
if __name__ == "__main__":
test()
=====================================
lib/python/web_support.py
=====================================
@@ -612,10 +612,6 @@ class WebServiceBase:
return Tag('html',
(HEAD(head_list), Tag('body', body_list, **body_attribs)))
- def pre_dispatch(self, url):
- """Invoked by handle prior to calling the registered handler."""
- pass
-
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
daemon_threads = True
@@ -644,7 +640,6 @@ class WebServiceHTTP(WebServiceBase):
service_self.lock.acquire()
try:
- service_self.pre_dispatch()
r = method(remaining, params, url)
assert isinstance(r, Result), repr(r)
result = r.flatten_later()
View it on GitLab: https://salsa.debian.org/security-tracker-team/security-tracker/-/compare/984693fef06e47d112744fd4be10ce9085f5c472...c0245516eac771990497444c9eba4da00d2ceea7
--
View it on GitLab: https://salsa.debian.org/security-tracker-team/security-tracker/-/compare/984693fef06e47d112744fd4be10ce9085f5c472...c0245516eac771990497444c9eba4da00d2ceea7
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-security-tracker-commits/attachments/20260807/2e500257/attachment-0001.htm>
More information about the debian-security-tracker-commits
mailing list