[Git][security-tracker-team/security-tracker][master] 2 commits: web_support.py: tighten the types/encoding of Result objects

Emilio Pozuelo Monfort (@pochu) pochu at debian.org
Thu Aug 6 08:46:15 BST 2026



Emilio Pozuelo Monfort pushed to branch master at Debian Security Tracker / security-tracker


Commits:
ae7f9d19 by Helmut Grohne at 2026-08-03T23:02:59+02:00
web_support.py: tighten the types/encoding of Result objects

The Result class encapsulates the data to be returned for a HTTP
request. The BinaryResult subclass consumes "contents" as str or bytes
and encodes it as needed. Unfortunately, the Content-Length is computed
on the str object. If the contents contain multibyte characters, more
data may be returned than is conveyed via the Content-Length. This is
bad. The BinaryResult now really wants a bytes object to be passed. All
callers are changed to provide one.

For the HTMLResult, we know that encoding is needed and can do so
unconditionally. Thus maybe_encode (and its broad exception catching)
goes away for good.

- - - - -
250c3830 by Emilio Pozuelo Monfort at 2026-08-06T07:46:12+00:00
Merge branch 'helmutg/web-result-encoding' into 'master'

web_support.py: tighten the types/encoding of Result objects

See merge request security-tracker-team/security-tracker!316
- - - - -


3 changed files:

- bin/tracker_service.py
- lib/python/security_db.py
- lib/python/web_support.py


Changes:

=====================================
bin/tracker_service.py
=====================================
@@ -156,7 +156,7 @@ class TrackerService(WebServiceHTTP):
         self.register('script.js', self.page_script_js)
 
     def page_style_css(self, path, params, url):
-        with open('../static/style.css', 'r') as f:
+        with open('../static/style.css', 'rb') as f:
             content=f.read()
             return BinaryResult(content,'text/css')
 
@@ -166,12 +166,12 @@ class TrackerService(WebServiceHTTP):
             return BinaryResult(content,'image/png')
 
     def page_distributions_json(self, path, params, url):
-        with open('../static/distributions.json', 'r') as f:
+        with open('../static/distributions.json', 'rb') as f:
             content=f.read()
             return BinaryResult(content,'application/json')
 
     def page_script_js(self, path, params, url):
-        with open('../static/script.js', 'r') as f:
+        with open('../static/script.js', 'rb') as f:
             content=f.read()
             return BinaryResult(content,'text/javascript')
 
@@ -1256,7 +1256,7 @@ Debian bug number.'''),
             data.append(':')
             data.append(str(bugs))
             data.append('\n')
-        return BinaryResult(''.join(data),'application/octet-stream')
+        return BinaryResult(''.join(data).encode("utf-8"), 'application/octet-stream')
 
     def exported_result(self, path, url):
         data = self.db.getExported(path)


=====================================
lib/python/security_db.py
=====================================
@@ -1885,6 +1885,7 @@ class DB:
         for (data, content_type, last_modified) in self.cursor().execute(
             "SELECT data, content_type, last_modified FROM export_data WHERE path = ?",
             (name,)):
+            assert isinstance(data, bytes)
             return (data, content_type, last_modified)
         return None
 


=====================================
lib/python/web_support.py
=====================================
@@ -512,11 +512,6 @@ class RedirectResult(Result):
             self.status = 302
         self.headers['Location'] = str(url)
 
-def maybe_encode(obj):
-    try:
-        return obj.encode()
-    except:
-        return obj
 
 class HTMLResult(Result):
     """An object of this class combines a status code with HTML contents."""
@@ -540,13 +535,12 @@ class HTMLResult(Result):
         buf.write(self.doctype)
         buf.write('\n')
         self.contents.flatten(buf.write)
-        buf = buf.getvalue()
-        buf = maybe_encode(buf)
-        self.headers['Content-Length'] = str(len(buf))
+        encoded_data = buf.getvalue().encode("utf-8")
+        self.headers['Content-Length'] = str(len(encoded_data))
         def later(req):
             headers_later(req)
             if req.command != 'HEAD':
-                req.wfile.write(buf)
+                req.wfile.write(encoded_data)
         return later
 
 class BinaryResult(Result):
@@ -569,7 +563,7 @@ class BinaryResult(Result):
         def later(req):
             headers_later(req)
             if req.command != 'HEAD':
-                req.wfile.write(maybe_encode(self.contents))
+                req.wfile.write(self.contents)
         return later
 
 class WebServiceBase:



View it on GitLab: https://salsa.debian.org/security-tracker-team/security-tracker/-/compare/8622a70c4bf57ab2aa7571b5ed55cbb5047872fb...250c3830e77af8ca015341a3dfd6f88cbb8c08e5

-- 
View it on GitLab: https://salsa.debian.org/security-tracker-team/security-tracker/-/compare/8622a70c4bf57ab2aa7571b5ed55cbb5047872fb...250c3830e77af8ca015341a3dfd6f88cbb8c08e5
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/20260806/b3c34282/attachment-0001.htm>


More information about the debian-security-tracker-commits mailing list