From a71dbd0fdbc8a03d400c59d0446595a995301d07 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Sat, 22 Jun 2024 04:49:29 +0200 Subject: [PATCH] In GET /process handler, catch malformed ?title_b64= params. --- plomtask/http.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/plomtask/http.py b/plomtask/http.py index 0626b4c..b7040f7 100644 --- a/plomtask/http.py +++ b/plomtask/http.py @@ -3,6 +3,7 @@ from __future__ import annotations from dataclasses import dataclass from typing import Any, Callable from base64 import b64encode, b64decode +from binascii import Error as binascii_Exception from http.server import BaseHTTPRequestHandler from http.server import HTTPServer from urllib.parse import urlparse, parse_qs @@ -187,8 +188,8 @@ class TaskHandler(BaseHTTPRequestHandler): returns successfully, or right after any exception is triggered – otherwise, race conditions become plausible. - Note that any POST attempt, even a failed one, may end in problematic - inconsistencies: + Note that otherwise any POST attempt, even a failed one, may end in + problematic inconsistencies: - if the POST handler experiences an Exception, changes to objects won't get written to the DB, but the changed objects may remain in @@ -225,8 +226,8 @@ class TaskHandler(BaseHTTPRequestHandler): if hasattr(self, handler_name): handler = getattr(self, handler_name) redir_target = f(self, handler) - if 'POST' != http_method: - clear_caches() + if 'POST' == http_method: + clear_caches() if redir_target: self.send_response(302) self.send_header('Location', redir_target) @@ -235,8 +236,8 @@ class TaskHandler(BaseHTTPRequestHandler): msg = f'{not_found_msg}: {self._site}' raise NotFoundException(msg) except HandledException as error: - if 'POST' != http_method: - clear_caches() + if 'POST' == http_method: + clear_caches() ctx = {'msg': error} self._send_page(ctx, 'msg', error.http_code) finally: @@ -475,13 +476,18 @@ class TaskHandler(BaseHTTPRequestHandler): owned_ids = self._params.get_all_int('has_step') title_64 = self._params.get_str('title_b64') if title_64: - title = b64decode(title_64.encode()).decode() + try: + title = b64decode(title_64.encode()).decode() + except binascii_Exception as exc: + msg = 'invalid base64 for ?title_b64=' + raise BadFormatException(msg) from exc process.title.set(title) + preset_top_step = None owners = process.used_as_step_by(self.conn) for step_id in owner_ids: owners += [Process.by_id(self.conn, step_id)] - preset_top_step = None for process_id in owned_ids: + Process.by_id(self.conn, process_id) # to ensure ID exists preset_top_step = process_id return {'process': process, 'is_new': process.id_ is None, 'preset_top_step': preset_top_step, -- 2.30.2