@ohos-graphics/stability-code-review 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +169 -0
  2. package/SKILL.md +518 -0
  3. package/bin/install.js +165 -0
  4. package/config/rules.yaml +445 -0
  5. package/config/whitelist.yaml +52 -0
  6. package/package.json +40 -0
  7. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_001.md +275 -0
  8. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_002.md +273 -0
  9. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_003.md +305 -0
  10. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_004.md +350 -0
  11. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_005.md +301 -0
  12. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_006.md +320 -0
  13. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_007.md +432 -0
  14. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_008.md +394 -0
  15. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_009.md +425 -0
  16. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_010.md +472 -0
  17. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_011.md +204 -0
  18. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_012.md +210 -0
  19. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_013.md +226 -0
  20. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_014.md +222 -0
  21. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_015.md +256 -0
  22. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_016.md +269 -0
  23. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_017.md +222 -0
  24. package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_018.md +336 -0
  25. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_001.md +414 -0
  26. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_002.md +335 -0
  27. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_003.md +284 -0
  28. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_004.md +313 -0
  29. package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_005.md +364 -0
  30. package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_001.md +142 -0
  31. package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_002.md +222 -0
  32. package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_003.md +383 -0
  33. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_001.md +258 -0
  34. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_002.md +131 -0
  35. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_003.md +220 -0
  36. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_004.md +224 -0
  37. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_005.md +250 -0
  38. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_006.md +153 -0
  39. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_007.md +169 -0
  40. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_008.md +153 -0
  41. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_009.md +144 -0
  42. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_010.md +152 -0
  43. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_011.md +221 -0
  44. package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_012.md +318 -0
  45. package/references/InitializationOrder/StabilityCodeReview_InitializationOrder_001.md +411 -0
  46. package/references/Lifecycle/StabilityCodeReview_Lifecycle_001.md +255 -0
  47. package/references/Lifecycle/StabilityCodeReview_Lifecycle_002.md +177 -0
  48. package/references/MemoryStability/StabilityCodeReview_MemoryStability_001.md +332 -0
  49. package/references/MemoryStability/StabilityCodeReview_MemoryStability_002.md +261 -0
  50. package/references/MemoryStability/StabilityCodeReview_MemoryStability_003.md +428 -0
  51. package/references/MemoryStability/StabilityCodeReview_MemoryStability_004.md +400 -0
  52. package/references/MemoryStability/StabilityCodeReview_MemoryStability_005.md +364 -0
  53. package/references/MemoryStability/StabilityCodeReview_MemoryStability_006.md +359 -0
  54. package/references/MemoryStability/StabilityCodeReview_MemoryStability_007.md +279 -0
  55. package/references/PROBLEM_TEMPLATE.md +65 -0
  56. package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_001.md +380 -0
  57. package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_002.md +437 -0
  58. package/references/REPORT_TEMPLATE.csv +5 -0
  59. package/references/REPORT_TEMPLATE.md +132 -0
  60. package/references/RULE_DEVELOPMENT_GUIDE.md +711 -0
  61. package/references/RULE_INDEX.md +101 -0
  62. package/references/RULE_TEMPLATE.md +192 -0
  63. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_001.md +334 -0
  64. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_002.md +425 -0
  65. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_003.md +420 -0
  66. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_004.md +409 -0
  67. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_005.md +445 -0
  68. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_006.md +384 -0
  69. package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_007.md +395 -0
  70. package/scripts/add-rule.py +423 -0
@@ -0,0 +1,472 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_010"
3
+ name: "容器find返回迭代器需校验有效性"
4
+ category: "边界条件"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # 容器find返回迭代器需校验有效性
11
+
12
+ ## 问题描述
13
+
14
+ 容器find返回的迭代器在使用前需要先校验有效性,直接使用可能为end()的迭代器会导致未定义行为、程序崩溃或内存访问错误。
15
+
16
+ ## 检测示例
17
+
18
+ ### ❌ 问题代码
19
+
20
+ ```cpp
21
+ // 错误示例1:map find后直接使用
22
+ std::map<int, std::string> dataMap;
23
+
24
+ std::string GetValue(int key)
25
+ {
26
+ auto it = dataMap.find(key);
27
+ return it->second; // 危险:it可能是end()
28
+ }
29
+
30
+ // 错误示例2:unordered_map直接访问
31
+ std::unordered_map<std::string, int> cache;
32
+
33
+ int GetCachedValue(const std::string& key)
34
+ {
35
+ auto it = cache.find(key);
36
+ return it->second; // 危险:未检查有效性
37
+ }
38
+
39
+ // 错误示例3:set find后直接访问
40
+ std::set<int> validIds;
41
+
42
+ bool IsValid(int id)
43
+ {
44
+ auto it = validIds.find(id);
45
+ return *it == id; // 危险:it可能是end()
46
+ }
47
+
48
+ // 错误示例4:vector find后访问
49
+ std::vector<int> numbers;
50
+
51
+ int GetFirstMatch(int value)
52
+ {
53
+ auto it = std::find(numbers.begin(), numbers.end(), value);
54
+ return *it; // 危险:it可能是end()
55
+ }
56
+
57
+ // 错误示例5:多重容器find
58
+ std::multimap<int, std::string> multiMap;
59
+
60
+ std::string GetFirstValue(int key)
61
+ {
62
+ auto it = multiMap.find(key);
63
+ return it->second; // 危险:未检查有效性
64
+ }
65
+
66
+ // 错误示例6:find后修改
67
+ std::map<int, Data> dataStore;
68
+
69
+ void UpdateData(int key, const Data& newData)
70
+ {
71
+ auto it = dataStore.find(key);
72
+ it->second = newData; // 危险:未检查有效性
73
+ }
74
+
75
+ // 错误示例7:find_if后使用
76
+ std::vector<Item> items;
77
+
78
+ Item* FindItemById(int id)
79
+ {
80
+ auto it = std::find_if(items.begin(), items.end(),
81
+ [id](const Item& item) { return item.id == id; });
82
+ return &(*it); // 危险:it可能是end()
83
+ }
84
+
85
+ // 错误示例8:find后访问成员
86
+ std::map<std::string, Config> configs;
87
+
88
+ int GetConfigValue(const std::string& name)
89
+ {
90
+ auto it = configs.find(name);
91
+ return it->second.value; // 危险:未检查有效性
92
+ }
93
+
94
+ // 错误示例9:find后删除
95
+ std::map<int, std::string> names;
96
+
97
+ void RemoveName(int id)
98
+ {
99
+ auto it = names.find(id);
100
+ names.erase(it); // 危险:erase(end())未定义
101
+ }
102
+
103
+ // 错误示例10:链式find调用
104
+ std::map<int, std::map<std::string, int>> nested;
105
+
106
+ int GetNestedValue(int outerKey, const std::string& innerKey)
107
+ {
108
+ auto outer = nested.find(outerKey);
109
+ auto inner = outer->second.find(innerKey); // 危险:outer可能是end()
110
+ return inner->second; // 危险:inner可能是end()
111
+ }
112
+
113
+ // 错误示例11:find后distance
114
+ std::vector<int> vec;
115
+
116
+ size_t GetIndex(int value)
117
+ {
118
+ auto it = std::find(vec.begin(), vec.end(), value);
119
+ return std::distance(vec.begin(), it); // 危险:it可能是end(),返回无效索引
120
+ }
121
+ ```
122
+
123
+ ### ✅ 修复方案
124
+
125
+ ```cpp
126
+ // 正确示例1:map find后检查有效性
127
+ std::map<int, std::string> dataMap;
128
+
129
+ std::string GetValue(int key)
130
+ {
131
+ auto it = dataMap.find(key);
132
+ if (it == dataMap.end()) { // 正确:检查有效性
133
+ return ""; // 或返回默认值
134
+ }
135
+ return it->second; // 安全:已验证有效
136
+ }
137
+
138
+ // 正确示例2:使用count()检查(更简洁)
139
+ std::map<int, std::string> dataMap;
140
+
141
+ std::string GetValue(int key)
142
+ {
143
+ if (dataMap.count(key) > 0) { // 正确:使用count检查
144
+ return dataMap[key]; // 安全:已确认存在
145
+ }
146
+ return "";
147
+ }
148
+
149
+ // 正确示例3:使用contains()检查(C++20,推荐)
150
+ std::map<int, std::string> dataMap;
151
+
152
+ std::string GetValue(int key)
153
+ {
154
+ if (dataMap.contains(key)) { // 正确:C++20 contains方法,语义更清晰
155
+ return dataMap[key]; // 安全:已确认存在
156
+ }
157
+ return "";
158
+ }
159
+
160
+ // 正确示例4:unordered_map find检查
161
+ std::unordered_map<std::string, int> cache;
162
+
163
+ int GetCachedValue(const std::string& key, int defaultValue = 0)
164
+ {
165
+ auto it = cache.find(key);
166
+ if (it != cache.end()) { // 正确:检查有效性
167
+ return it->second;
168
+ }
169
+ return defaultValue; // 返回默认值
170
+ }
171
+
172
+ // 正确示例5:使用contains()替代find()(推荐)
173
+ std::unordered_map<std::string, int> cache;
174
+
175
+ bool HasCachedValue(const std::string& key)
176
+ {
177
+ return cache.contains(key); // 正确:C++20 contains,更简洁
178
+ }
179
+
180
+ int GetCachedValueSafe(const std::string& key)
181
+ {
182
+ if (cache.contains(key)) { // 正确:先检查存在性
183
+ return cache[key]; // 安全访问
184
+ }
185
+ return 0; // 默认值
186
+ }
187
+ return it->second;
188
+ }
189
+
190
+ // 正确示例2:unordered_map安全访问
191
+ std::unordered_map<std::string, int> cache;
192
+
193
+ int GetCachedValue(const std::string& key)
194
+ {
195
+ auto it = cache.find(key);
196
+ if (it != cache.end()) { // 正确:先检查
197
+ return it->second;
198
+ }
199
+ LOGE("Cache miss for key: %s", key.c_str());
200
+ return -1;
201
+ }
202
+
203
+ // 正确示例3:set find安全使用
204
+ std::set<int> validIds;
205
+
206
+ bool IsValid(int id)
207
+ {
208
+ return validIds.find(id) != validIds.end(); // 正确:直接返回检查结果
209
+ }
210
+
211
+ // 正确示例4:vector find安全访问
212
+ std::vector<int> numbers;
213
+
214
+ int GetFirstMatch(int value, int defaultValue = -1)
215
+ {
216
+ auto it = std::find(numbers.begin(), numbers.end(), value);
217
+ if (it == numbers.end()) { // 正确:先检查
218
+ return defaultValue;
219
+ }
220
+ return *it;
221
+ }
222
+
223
+ // 正确示例5:多重容器find安全使用
224
+ std::multimap<int, std::string> multiMap;
225
+
226
+ std::string GetFirstValue(int key)
227
+ {
228
+ auto it = multiMap.find(key);
229
+ if (it == multiMap.end()) { // 正确:先检查
230
+ return "";
231
+ }
232
+ return it->second;
233
+ }
234
+
235
+ // 正确示例6:find后安全修改
236
+ std::map<int, Data> dataStore;
237
+
238
+ bool UpdateData(int key, const Data& newData)
239
+ {
240
+ auto it = dataStore.find(key);
241
+ if (it == dataStore.end()) { // 正确:先检查
242
+ LOGE("Key not found: %d", key);
243
+ return false;
244
+ }
245
+ it->second = newData;
246
+ return true;
247
+ }
248
+
249
+ // 正确示例7:find_if安全使用
250
+ std::vector<Item> items;
251
+
252
+ Item* FindItemById(int id)
253
+ {
254
+ auto it = std::find_if(items.begin(), items.end(),
255
+ [id](const Item& item) { return item.id == id; });
256
+ if (it == items.end()) { // 正确:先检查
257
+ return nullptr;
258
+ }
259
+ return &(*it);
260
+ }
261
+
262
+ // 正确示例8:find后安全访问成员
263
+ std::map<std::string, Config> configs;
264
+
265
+ int GetConfigValue(const std::string& name, int defaultValue = 0)
266
+ {
267
+ auto it = configs.find(name);
268
+ if (it == configs.end()) { // 正确:先检查
269
+ return defaultValue;
270
+ }
271
+ return it->second.value;
272
+ }
273
+
274
+ // 正确示例9:find后安全删除
275
+ std::map<int, std::string> names;
276
+
277
+ bool RemoveName(int id)
278
+ {
279
+ auto it = names.find(id);
280
+ if (it == names.end()) { // 正确:先检查
281
+ LOGE("Name not found for id: %d", id);
282
+ return false;
283
+ }
284
+ names.erase(it);
285
+ return true;
286
+ }
287
+
288
+ // 正确示例10:链式find安全调用
289
+ std::map<int, std::map<std::string, int>> nested;
290
+
291
+ int GetNestedValue(int outerKey, const std::string& innerKey)
292
+ {
293
+ auto outer = nested.find(outerKey);
294
+ if (outer == nested.end()) { // 正确:先检查外层
295
+ LOGE("Outer key not found: %d", outerKey);
296
+ return -1;
297
+ }
298
+ auto inner = outer->second.find(innerKey);
299
+ if (inner == outer->second.end()) { // 正确:再检查内层
300
+ LOGE("Inner key not found: %s", innerKey.c_str());
301
+ return -1;
302
+ }
303
+ return inner->second;
304
+ }
305
+
306
+ // 正确示例11:find后安全distance
307
+ std::vector<int> vec;
308
+
309
+ bool GetIndex(int value, size_t& index)
310
+ {
311
+ auto it = std::find(vec.begin(), vec.end(), value);
312
+ if (it == vec.end()) { // 正确:先检查
313
+ return false;
314
+ }
315
+ index = std::distance(vec.begin(), it);
316
+ return true;
317
+ }
318
+
319
+ // 正确示例12:使用辅助函数
320
+ template<typename Container, typename Key>
321
+ typename Container::mapped_type SafeFind(
322
+ Container& container,
323
+ const Key& key,
324
+ typename Container::mapped_type defaultValue = {}
325
+ ) {
326
+ auto it = container.find(key);
327
+ if (it == container.end()) {
328
+ return defaultValue;
329
+ }
330
+ return it->second;
331
+ }
332
+
333
+ // 使用
334
+ std::map<int, std::string> map;
335
+ std::string value = SafeFind(map, key, "");
336
+
337
+ // 正确示例13:使用contains检查(C++20)
338
+ std::map<int, std::string> dataMap;
339
+
340
+ bool HasKey(int key)
341
+ {
342
+ return dataMap.contains(key); // C++20: 直接检查是否存在
343
+ }
344
+
345
+ std::string GetValue(int key)
346
+ {
347
+ if (dataMap.contains(key)) { // 正确:先检查
348
+ return dataMap[key];
349
+ }
350
+ return "";
351
+ }
352
+ ```
353
+
354
+ ## 检测范围
355
+
356
+ 检查以下模式:
357
+
358
+ 1. `container.find(key)` 后直接使用 `->`
359
+ 2. `std::find(begin, end, value)` 后直接使用 `*`
360
+ 3. `std::find_if(...)` 后直接访问
361
+ 4. find返回值用于erase但未检查
362
+ 5. 链式find调用未逐层检查
363
+
364
+ ## 检测要点
365
+
366
+ 1. 识别`find`, `find_if`函数调用
367
+ 2. 检查返回的迭代器是否与`end()`比较
368
+ 3. 检查在`if (it != end())`条件内使用
369
+ 4. 识别`->second`, `->first`, `*it`等访问操作
370
+ 5. 排除NOPROTECT标记的代码
371
+
372
+ ## 风险流分析(RiskFlow)
373
+
374
+ - **RISK_SOURCE**: find返回可能为end()的迭代器
375
+ - **RISK_TYPE**: 使用无效迭代器
376
+ - **RISK_PATH**: find -> 未检查 -> 直接访问 -> 未定义行为
377
+ - **IMPACT_POINT**: 程序崩溃、内存访问错误
378
+
379
+ ## 影响分析(ImpactAnalysis)
380
+
381
+ - **Trigger**: find后未校验迭代器有效性
382
+ - **Propagation**: end()迭代器访问导致崩溃
383
+ - **Consequence**: 程序崩溃、数据损坏、未定义行为
384
+ - **Mitigation**: 使用前与end()比较,或使用contains/count
385
+
386
+ ## 误报排除
387
+
388
+ | 场景 | 识别特征 | 处理方式 |
389
+ |------|----------|----------|
390
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
391
+ | 已有end检查 | 存在 != end() 或 == end() 判断 | 不报 |
392
+ | 在条件内使用 | 在 if 条件返回true后使用 | 不报 |
393
+ | 使用contains | 使用C++20 contains() | 不报 |
394
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
395
+ ## 测试用例
396
+
397
+ ### 触发用例(应该报)
398
+
399
+ ```cpp
400
+ // test_BoundaryCondition_010_trigger.cpp
401
+ std::map<int, std::string> map;
402
+
403
+ std::string trigger_bad_1(int key)
404
+ {
405
+ auto it = map.find(key);
406
+ return it->second; // 应该报:未检查end()
407
+ }
408
+
409
+ std::vector<int> vec;
410
+
411
+ int trigger_bad_2(int value)
412
+ {
413
+ auto it = std::find(vec.begin(), vec.end(), value);
414
+ return *it; // 应该报:未检查end()
415
+ }
416
+
417
+ std::set<int> set;
418
+
419
+ bool trigger_bad_3(int id)
420
+ {
421
+ auto it = set.find(id);
422
+ return *it == id; // 应该报:未检查end()
423
+ }
424
+
425
+ std::map<int, Data> dataMap;
426
+
427
+ void trigger_bad_4(int key)
428
+ {
429
+ auto it = dataMap.find(key);
430
+ it->second.value = 0; // 应该报:未检查end()
431
+ }
432
+ ```
433
+
434
+ ### 安全用例(不应该报)
435
+
436
+ ```cpp
437
+ // test_BoundaryCondition_010_safe.cpp
438
+ std::map<int, std::string> map;
439
+
440
+ std::string safe_good_1(int key)
441
+ {
442
+ auto it = map.find(key);
443
+ if (it == map.end()) { // 安全:有检查
444
+ return "";
445
+ }
446
+ return it->second;
447
+ }
448
+
449
+ std::string safe_good_2(int key)
450
+ {
451
+ auto it = map.find(key);
452
+ if (it != map.end()) { // 安全:有检查
453
+ return it->second;
454
+ }
455
+ return "";
456
+ }
457
+
458
+ int safe_good_3(int key)
459
+ {
460
+ if (map.count(key) > 0) { // 安全:使用count检查
461
+ return map[key].length();
462
+ }
463
+ return 0;
464
+ }
465
+
466
+ // NOPROTECT: 特殊处理场景
467
+ std::string noprotect_case(int key)
468
+ {
469
+ auto it = map.find(key);
470
+ return it->second;
471
+ }
472
+ ```
@@ -0,0 +1,204 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_011"
3
+ name: "加减乘除运算应避免类型溢出或回绕"
4
+ category: "边界条件"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # 加减乘除运算应避免类型溢出或回绕
11
+
12
+ ## 问题描述
13
+
14
+ 整数运算时未检查溢出,可能导致数值回绕、逻辑错误或安全问题。尤其在内存分配大小计算、数组索引计算等关键场景,溢出可能导致内存分配不足或越界访问。
15
+
16
+ ## 检测示例
17
+
18
+ ### ❌ 问题代码
19
+
20
+ ```cpp
21
+ // 错误示例1:乘法溢出导致内存分配不足
22
+ void AllocateBuffer(int count, int itemSize)
23
+ {
24
+ int totalSize = count * itemSize; // 危险:可能溢出
25
+ char* buffer = new char[totalSize];
26
+ // ...
27
+ }
28
+
29
+ // 错误示例2:加法溢出
30
+ void ProcessData(int offset, int length)
31
+ {
32
+ int end = offset + length; // 危险:可能溢出
33
+ for (int i = offset; i < end; i++) {
34
+ ProcessItem(i);
35
+ }
36
+ }
37
+
38
+ // 错误示例3:减法回绕(无符号)
39
+ void CopyData(uint32_t start, uint32_t end)
40
+ {
41
+ uint32_t size = end - start; // 危险:若end < start,回绕到超大值
42
+ char* buffer = new char[size];
43
+ // ...
44
+ }
45
+
46
+ // 错误示例4:计算缓冲区大小
47
+ int CalculateBufferSize(int width, int height, int bpp)
48
+ {
49
+ return width * height * bpp; // 危险:多次乘法可能溢出
50
+ }
51
+ ```
52
+
53
+ ### ✅ 修复方案
54
+
55
+ ```cpp
56
+ // 正确示例1:乘法溢出检查
57
+ void AllocateBuffer(int count, int itemSize)
58
+ {
59
+ // 检查乘法溢出
60
+ if (itemSize > 0 && count > INT_MAX / itemSize) {
61
+ LOGE("Multiplication overflow: %d * %d", count, itemSize);
62
+ return;
63
+ }
64
+ int totalSize = count * itemSize;
65
+ if (totalSize <= 0) {
66
+ LOGE("Invalid size: %d", totalSize);
67
+ return;
68
+ }
69
+ char* buffer = new char[totalSize];
70
+ // ...
71
+ }
72
+
73
+ // 正确示例2:使用安全整数运算库
74
+ void AllocateBufferSafe(int count, int itemSize)
75
+ {
76
+ int totalSize;
77
+ if (!base::CheckMul(count, itemSize).AssignIfValid(&totalSize)) {
78
+ LOGE("Multiplication overflow");
79
+ return;
80
+ }
81
+ char* buffer = new char[totalSize];
82
+ // ...
83
+ }
84
+
85
+ // 正确示例3:使用saturated_cast
86
+ void ProcessData(int offset, int length)
87
+ {
88
+ int64_t end = base::saturated_cast<int64_t>(offset) +
89
+ base::saturated_cast<int64_t>(length);
90
+ if (end > INT_MAX || end < offset) {
91
+ LOGE("Addition overflow");
92
+ return;
93
+ }
94
+ for (int i = offset; i < static_cast<int>(end); i++) {
95
+ ProcessItem(i);
96
+ }
97
+ }
98
+
99
+ // 正确示例4:使用64位中间值
100
+ int64_t CalculateBufferSize(int width, int height, int bpp)
101
+ {
102
+ int64_t size = static_cast<int64_t>(width) *
103
+ static_cast<int64_t>(height) *
104
+ static_cast<int64_t>(bpp);
105
+ if (size > INT_MAX || size <= 0) {
106
+ LOGE("Buffer size overflow or invalid");
107
+ return -1;
108
+ }
109
+ return static_cast<int>(size);
110
+ }
111
+ ```
112
+
113
+ ## 检测范围
114
+
115
+ 检查以下运算模式:
116
+
117
+ - `a * b`、`a * b * c` 等乘法运算
118
+ - `a + b`、`a + b + c` 等加法运算
119
+ - `a - b` 减法运算(特别是无符号类型)
120
+ - 内存分配大小计算:`malloc(a * b)`、`new char[a * b]`
121
+ - 数组索引计算:`array[a + b]`、`array[a * b]`
122
+
123
+ ## 检测要点
124
+
125
+ 1. 识别算术运算表达式(+、-、*)
126
+ 2. 检查是否在内存分配上下文中使用
127
+ 3. 检查是否在数组索引上下文中使用
128
+ 4. 检查是否存在溢出保护机制
129
+ 5. 排除NOPROTECT标记的代码
130
+
131
+ ## 风险流分析(RiskFlow)
132
+
133
+ - **RISK_SOURCE**: 整数运算表达式
134
+ - **RISK_TYPE**: 整数溢出/回绕
135
+ - **RISK_PATH**: 运算结果溢出 -> 数值回绕 -> 内存分配错误/数组越界
136
+ - **IMPACT_POINT**: 内存损坏、安全漏洞、程序崩溃
137
+
138
+ ## 影响分析(ImpactAnalysis)
139
+
140
+ - **Trigger**: 运算结果超出类型表示范围
141
+ - **Propagation**: 结果回绕为负值或意外大值
142
+ - **Consequence**: 内存分配不足、缓冲区溢出、数据损坏
143
+ - **Mitigation**: 使用安全整数运算库或添加溢出检查
144
+
145
+ ## 误报排除
146
+
147
+ | 场景 | 识别特征 | 处理方式 |
148
+ |------|----------|----------|
149
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
150
+ | 已有溢出检查 | 存在 INT_MAX、溢出函数调用 | 不报 |
151
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
152
+ | 测试代码 | 位于 test 目录 | 自动跳过 |
153
+ | 常量运算 | 编译期可计算的表达式 | 不报 |
154
+ ## 测试用例
155
+
156
+ ### 触发用例(应该报)
157
+
158
+ ```cpp
159
+ // test_BoundaryCondition_011_trigger.cpp
160
+ void trigger_bad_1(int count, int itemSize)
161
+ {
162
+ int total = count * itemSize; // 应该报:乘法溢出风险
163
+ char* buffer = new char[total];
164
+ }
165
+
166
+ void trigger_bad_2(int a, int b, int c)
167
+ {
168
+ int size = a * b * c; // 应该报:多次乘法溢出风险
169
+ ProcessBuffer(size);
170
+ }
171
+
172
+ void trigger_bad_3(uint32_t start, uint32_t end)
173
+ {
174
+ uint32_t size = end - start; // 应该报:无符号减法回绕风险
175
+ char* buffer = new char[size];
176
+ }
177
+ ```
178
+
179
+ ### 安全用例(不应该报)
180
+
181
+ ```cpp
182
+ // test_BoundaryCondition_011_safe.cpp
183
+ void safe_good_1(int count, int itemSize)
184
+ {
185
+ if (itemSize > 0 && count <= INT_MAX / itemSize) { // 安全:有溢出检查
186
+ int total = count * itemSize;
187
+ char* buffer = new char[total];
188
+ }
189
+ }
190
+
191
+ void safe_good_2(int count, int itemSize)
192
+ {
193
+ int total = base::saturated_cast<int>(
194
+ static_cast<int64_t>(count) * itemSize); // 安全:使用saturated
195
+ char* buffer = new char[total];
196
+ }
197
+
198
+ // NOPROTECT: 常量运算不会溢出
199
+ void noprotect_case()
200
+ {
201
+ const int SIZE = 10 * 20; // 编译期常量,不报
202
+ char buffer[SIZE];
203
+ }
204
+ ```