No.006 · 编程
代码审查:只挑会出事的问题
让模型别纠结命名和格式,只找 bug、安全和边界情况。
提示词
请审查下面的代码:
【粘贴代码】
只指出会导致错误结果、崩溃、安全问题或性能明显变差的地方。
每条写:在哪一行、为什么有问题、怎么改。
命名、格式、注释风格一律不用提。没有问题就直接说没有。
示例:填好之后,模型这样回答
填好后的提示词(示例内容为虚构)
请审查下面的代码:
def get_balance(uid):
rows = db.query(f"SELECT balance FROM acct_tbl WHERE uid = '{uid}'")
if not rows:
return 0
return rows[0]['balance']
def transfer(src, dst, amount):
if get_balance(src) >= amount:
db.execute(f"UPDATE acct_tbl SET balance = balance - {amount} WHERE uid = '{src}'")
db.execute(f"UPDATE acct_tbl SET balance = balance + {amount} WHERE uid = '{dst}'")
只指出会导致错误结果、崩溃、安全问题或性能明显变差的地方。
每条写:在哪一行、为什么有问题、怎么改。
命名、格式、注释风格一律不用提。没有问题就直接说没有。模型回答 · claude-sonnet-5-5 · 2026-10-24 实跑,未修改
问题清单
1. 第 2 行:SQL 注入uid 被直接拼进 SQL。传入 ' OR '1'='1 之类的值就能读到任意数据。
改法:使用参数化查询。
rows = db.query("SELECT balance FROM acct_tbl WHERE uid = %s", (uid,))占位符风格按你用的驱动调整,如 %s、?、:uid。
2. 第 9、10 行:SQL 注入,且 amount 也可被注入src、dst、amount 全部是拼接的。amount 没有引号,注入更容易,例如 "0; UPDATE acct_tbl SET balance=999999 WHERE uid='x"。
改法:全部参数化,见文末示例。
3. 第 8–10 行:检查再更新存在竞态(TOCTOU),可能透支
并发两笔转账都可能读到足够的余额,然后都扣款,余额变成负数。
改法:把检查合并进 UPDATE 的条件里,并检查影响行数。
UPDATE acct_tbl SET balance = balance - %s WHERE uid = %s AND balance >= %s
`rowcount != 1
不同模型、不同时间的回答会有差异;想对比几个模型,可以把这段提示词拿到提示词实验室并排跑一遍。
注意
- “没有问题就直接说没有”能减少它为了凑数编出来的建议。