From 2211cebec9fd4a971b7b9f5cd732d922fb4cebe8 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 00:58:21 +0000 Subject: [PATCH] Fix SQL injection vulnerabilities in Quiz_4.py Replaced string formatting with parameterized queries in insertPC, updatePrinter, and deleteLaptop functions to properly sanitize inputs and prevent SQL injection. Added unit tests using an in-memory SQLite database to ensure the methods still work correctly and prevent future regressions. Co-authored-by: tsainez <13399044+tsainez@users.noreply.github.com> --- python/Quiz_4.py | 16 +++---- python/test_Quiz_4.py | 108 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 python/test_Quiz_4.py diff --git a/python/Quiz_4.py b/python/Quiz_4.py index 454f0b6..9a50dbf 100644 --- a/python/Quiz_4.py +++ b/python/Quiz_4.py @@ -149,16 +149,16 @@ def insertPC(_conn, _maker, _model, _speed, _ram, _hd, _price): print(l) cursor = _conn.cursor() - cursor.execute('DELETE FROM pc WHERE model = {};'.format(_model)) + cursor.execute('DELETE FROM pc WHERE model = ?;', (_model,)) - cursor.execute('DELETE FROM product WHERE model = {};'.format(_model)) + cursor.execute('DELETE FROM product WHERE model = ?;', (_model,)) cursor.execute( - 'INSERT INTO pc(model, speed, ram, hd, price) VALUES(\'{}\', {}, {}, {}, {});'.format( - _model, _speed, _ram, _hd, _price)) + 'INSERT INTO pc(model, speed, ram, hd, price) VALUES(?, ?, ?, ?, ?);', + (_model, _speed, _ram, _hd, _price)) - cursor.execute('INSERT INTO product(maker, model, TYPE) VALUES(\'{}\', {}, \'{}\');'.format( - _maker, _model, 'PC')) + cursor.execute('INSERT INTO product(maker, model, TYPE) VALUES(?, ?, ?);', + (_maker, _model, 'PC')) _conn.commit() print("++++++++++++++++++++++++++++++++++") @@ -179,7 +179,7 @@ def updatePrinter(_conn, _model, _price): cursor = _conn.cursor() # Fixed typo from original code: exucte -> execute cursor.execute( - 'UPDATE printer SET price = {} WHERE model = {};'.format(_price, _model)) + 'UPDATE printer SET price = ? WHERE model = ?;', (_price, _model)) _conn.commit() print("++++++++++++++++++++++++++++++++++") @@ -198,7 +198,7 @@ def deleteLaptop(_conn, _model): print(l) cursor = _conn.cursor() - cursor.execute('DELETE FROM laptop WHERE model = {}'.format(_model)) + cursor.execute('DELETE FROM laptop WHERE model = ?;', (_model,)) _conn.commit() print("++++++++++++++++++++++++++++++++++") diff --git a/python/test_Quiz_4.py b/python/test_Quiz_4.py new file mode 100644 index 0000000..eef94eb --- /dev/null +++ b/python/test_Quiz_4.py @@ -0,0 +1,108 @@ +import unittest +import sqlite3 +import os +from Quiz_4 import insertPC, updatePrinter, deleteLaptop, createPriceRange + +class TestQuiz4SecurityFix(unittest.TestCase): + def setUp(self): + # Create an in-memory SQLite database + self.conn = sqlite3.connect(':memory:') + self.cursor = self.conn.cursor() + + # Create tables as expected by the script + self.cursor.execute(''' + CREATE TABLE product ( + maker TEXT, + model INTEGER PRIMARY KEY, + type TEXT + ) + ''') + self.cursor.execute(''' + CREATE TABLE pc ( + model INTEGER PRIMARY KEY, + speed REAL, + ram INTEGER, + hd INTEGER, + price INTEGER + ) + ''') + self.cursor.execute(''' + CREATE TABLE laptop ( + model INTEGER PRIMARY KEY, + speed REAL, + ram INTEGER, + hd INTEGER, + screen REAL, + price INTEGER + ) + ''') + self.cursor.execute(''' + CREATE TABLE printer ( + model INTEGER PRIMARY KEY, + color TEXT, + type TEXT, + price INTEGER + ) + ''') + self.conn.commit() + + def tearDown(self): + self.conn.close() + + def test_insertPC_parameterized(self): + # Test that insertPC works correctly and doesn't suffer from string formatting issues + maker = "MakerA" + model = 1001 + speed = 3.2 + ram = 16 + hd = 500 + price = 1200 + + insertPC(self.conn, maker, model, speed, ram, hd, price) + + self.cursor.execute("SELECT * FROM pc WHERE model=?", (model,)) + pc_record = self.cursor.fetchone() + self.assertIsNotNone(pc_record) + self.assertEqual(pc_record[0], model) + self.assertEqual(pc_record[4], price) + + self.cursor.execute("SELECT * FROM product WHERE model=?", (model,)) + product_record = self.cursor.fetchone() + self.assertIsNotNone(product_record) + self.assertEqual(product_record[0], maker) + + def test_updatePrinter_parameterized(self): + # Insert a printer to update + model = 2001 + initial_price = 150 + self.cursor.execute("INSERT INTO printer (model, color, type, price) VALUES (?, 'true', 'laser', ?)", (model, initial_price)) + self.cursor.execute("INSERT INTO product (maker, model, type) VALUES ('MakerB', ?, 'printer')", (model,)) + self.conn.commit() + + new_price = 200 + updatePrinter(self.conn, model, new_price) + + self.cursor.execute("SELECT price FROM printer WHERE model=?", (model,)) + updated_price = self.cursor.fetchone()[0] + self.assertEqual(updated_price, new_price) + + def test_deleteLaptop_parameterized(self): + # Insert a laptop to delete + model = 3001 + self.cursor.execute("INSERT INTO laptop (model, speed, ram, hd, screen, price) VALUES (?, 2.0, 8, 256, 15.6, 800)", (model,)) + self.cursor.execute("INSERT INTO product (maker, model, type) VALUES ('MakerC', ?, 'laptop')", (model,)) + self.conn.commit() + + # Verify it's there + self.cursor.execute("SELECT * FROM laptop WHERE model=?", (model,)) + self.assertIsNotNone(self.cursor.fetchone()) + + # Delete it + deleteLaptop(self.conn, model) + + # Verify it's gone + self.cursor.execute("SELECT * FROM laptop WHERE model=?", (model,)) + self.assertIsNone(self.cursor.fetchone()) + +if __name__ == '__main__': + unittest.main()