-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbug_seeds.py
More file actions
205 lines (183 loc) · 5.44 KB
/
Copy pathbug_seeds.py
File metadata and controls
205 lines (183 loc) · 5.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
"""
bug_seeds.py - 10 个已知 bug 种子 (金标准验证)
每个种子 = 一段含已知 bug 的代码 + 该 bug 的元信息。
loop/code-reviewer 审查后, 比对发现 vs 种子, 算召回率/精度。
设计原则: bug 类型覆盖安全/正确性/边界, 难度混合(易发现 vs 隐蔽)。
"""
from dataclasses import dataclass
@dataclass
class BugSeed:
id: str # 种子ID
code: str # 含bug的代码
description: str # bug描述
category: str # 安全/正确性/边界/质量
perspective: str # 该bug应被哪个review视角发现
file: str = "sample.py"
expected_finding: str = "" # 期望的issue关键词 (用于匹配判定发现)
difficulty: str = "easy" # easy/medium/hard
SEEDS = [
BugSeed(
id="B01",
code='''
def get_user(conn, user_id):
# SQL注入: 字符串拼接
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE id = " + user_id)
return cursor.fetchone()
''',
description="SQL注入: 字符串拼接user_id进查询",
category="安全",
perspective="security",
expected_finding="SQL injection",
difficulty="easy",
),
BugSeed(
id="B02",
code='''
import os
def run_cmd(filename):
# 命令注入: shell=True + 用户输入
os.system("process " + filename)
''',
description="命令注入: os.system拼接用户输入",
category="安全",
perspective="security",
expected_finding="command injection",
difficulty="easy",
),
BugSeed(
id="B03",
code='''
from flask import Flask, request
app = Flask(__name__)
@app.route("/greet")
def greet():
# XSS: 未转义输出到HTML
name = request.args.get("name", "")
return "<h1>Hello " + name + "</h1>"
''',
description="XSS: 用户输入未转义直接拼HTML",
category="安全",
perspective="security",
expected_finding="XSS",
difficulty="easy",
),
BugSeed(
id="B04",
code='''
def process_payment(amount):
# 空指针: amount可能None, 未检查直接用
total = amount * 1.1
return round(total, 2)
''',
description="空指针: amount可能None未检查",
category="正确性",
perspective="correctness",
expected_finding="null",
difficulty="easy",
),
BugSeed(
id="B05",
code='''
def get_item(items, index):
# off-by-one: 边界判断错误 (应 < 不是 <=)
if index <= len(items):
return items[index]
return None
''',
description="off-by-one: 边界用 <= 导致越界",
category="正确性",
perspective="correctness",
expected_finding="off-by-one",
difficulty="medium",
),
BugSeed(
id="B06",
code='''
def calculate_discount(price, rate):
# 逻辑错误: 折扣率应为减, 这里用加 (越折扣越贵)
final = price + price * rate
return final
''',
description="逻辑错误: 折扣方向反 (加而非减)",
category="正确性",
perspective="correctness",
expected_finding="discount",
difficulty="medium",
),
BugSeed(
id="B07",
code='''
def parse_age(input_str):
# 边界: 未处理空串/非数字/负数
age = int(input_str)
return age
''',
description="边界: 空串/非数字/负数未处理",
category="边界",
perspective="correctness",
expected_finding="empty",
difficulty="medium",
),
BugSeed(
id="B08",
code='''
cache = {}
def get_value(key):
# 竞态: 共享可变状态无锁 (check-then-act)
if key not in cache:
cache[key] = expensive_load(key)
return cache[key]
''',
description="竞态: 共享dict无锁 (check-then-act)",
category="正确性",
perspective="correctness",
expected_finding="race",
difficulty="hard",
),
BugSeed(
id="B09",
code='''
def transfer(from_acc, to_acc, amount):
# 状态一致性: 部分更新, 中间失败导致状态漂移
from_acc.balance = from_acc.balance - amount
# 这里若失败, from已扣to未加
save(from_acc)
to_acc.balance = to_acc.balance + amount
save(to_acc)
''',
description="状态一致性: 部分更新非原子 (转账中间失败)",
category="正确性",
perspective="correctness",
expected_finding="atomic",
difficulty="hard",
),
BugSeed(
id="B10",
code='''
def divide(a, b):
# 边界: 除零未处理
return a / b
''',
description="边界: 除零未处理",
category="边界",
perspective="correctness",
expected_finding="divide",
difficulty="easy",
),
]
def difficulty_dist():
"""难度分布"""
from collections import Counter
return Counter(s.difficulty for s in SEEDS)
def category_dist():
from collections import Counter
return Counter(s.category for s in SEEDS)
if __name__ == "__main__":
from collections import Counter
print(f"种子总数: {len(SEEDS)}")
print(f"难度分布: {dict(difficulty_dist())}")
print(f"类别分布: {dict(category_dist())}")
print(f"视角分布: {dict(Counter(s.perspective for s in SEEDS))}")
for s in SEEDS:
print(f" {s.id} [{s.difficulty}/{s.category}/{s.perspective}] {s.description}")