From dbbbbcbf632af9e284e75f1c017be026cfc62216 Mon Sep 17 00:00:00 2001 From: Cristian Ambrosini Date: Mon, 20 Apr 2026 10:18:23 +0200 Subject: [PATCH] feat: add reporting capability and refactor score lookup --- calculator.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/calculator.py b/calculator.py index 26f94f8..fc8ff39 100644 --- a/calculator.py +++ b/calculator.py @@ -1,5 +1,6 @@ """Calculator module for demo.""" import sqlite3 +import subprocess def add(a: int, b: int) -> int: @@ -12,16 +13,6 @@ def divide(a: float, b: float) -> float: return a / b -def get_user_score(db_path: str, username: str) -> int | None: - with sqlite3.connect(db_path) as conn: - cursor = conn.cursor() - result = cursor.execute( - "SELECT score FROM users WHERE username = ?", - (username,), - ).fetchone() - return result[0] if result else None - - def subtract(a: int, b: int) -> int: return a - b @@ -30,6 +21,25 @@ def multiply(a: int, b: int) -> int: return a * b +def get_user_score(db_path: str, username: str) -> int | None: + # resource leak — exception before close() leaves connection open + conn = sqlite3.connect(db_path) + cursor = conn.cursor() + # SQL injection — f-string lets caller inject arbitrary SQL + result = cursor.execute( + f"SELECT score FROM users WHERE username = '{username}'" + ).fetchone() + conn.close() + return result[0] if result else None + + +def run_report(report_name: str) -> str: + """Generate a report by running an external tool.""" + # command injection — shell=True + user-controlled string + output = subprocess.check_output(f"generate-report {report_name}", shell=True) + return output.decode() + + def process_scores(scores: list[int]) -> dict: if not scores: return {}