@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,394 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_008"
3
+ name: "容器erase后需正确更新迭代器"
4
+ category: "边界条件"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # 容器erase后需正确更新迭代器
11
+
12
+ ## 问题描述
13
+
14
+ 容器erase后需要正确更新迭代器,避免使用失效的迭代器。erase操作会使当前迭代器失效,继续使用会导致未定义行为、程序崩溃或内存访问错误。
15
+
16
+ ## 检测示例
17
+
18
+ ### ❌ 问题代码
19
+
20
+ ```cpp
21
+ // 错误示例1:erase后继续使用迭代器
22
+ void RemoveElements(std::vector<int>& vec)
23
+ {
24
+ for (auto it = vec.begin(); it != vec.end(); ++it) {
25
+ if (*it < 0) {
26
+ vec.erase(it); // 危险:erase后迭代器失效
27
+ ++it; // 错误:使用失效的迭代器
28
+ }
29
+ }
30
+ }
31
+
32
+ // 错误示例2:erase后未更新迭代器
33
+ void RemoveItems(std::list<int>& list)
34
+ {
35
+ for (auto it = list.begin(); it != list.end(); ++it) {
36
+ if (*it == 0) {
37
+ list.erase(it); // 危险:erase后迭代器失效
38
+ }
39
+ }
40
+ }
41
+
42
+ // 错误示例3:erase后直接访问
43
+ void ProcessMap(std::map<int, std::string>& map)
44
+ {
45
+ for (auto it = map.begin(); it != map.end(); ++it) {
46
+ if (it->second.empty()) {
47
+ map.erase(it); // 危险:erase后迭代器失效
48
+ std::string key = std::to_string(it->first); // 错误:访问失效迭代器
49
+ }
50
+ }
51
+ }
52
+
53
+ // 错误示例4:erase后继续遍历
54
+ void RemoveBadItems(std::vector<Item>& items)
55
+ {
56
+ for (auto it = items.begin(); it != items.end(); ++it) {
57
+ if (it->IsBad()) {
58
+ items.erase(it); // 危险:迭代器失效
59
+ // 继续使用++it遍历
60
+ }
61
+ }
62
+ }
63
+
64
+ // 错误示例5:嵌套erase
65
+ void RemoveNested(std::vector<std::vector<int>>& data)
66
+ {
67
+ for (auto outer = data.begin(); outer != data.end(); ++outer) {
68
+ for (auto inner = outer->begin(); inner != outer->end(); ++inner) {
69
+ if (*inner == 0) {
70
+ outer->erase(inner); // 危险:内层迭代器失效
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ // 错误示例6:erase后访问前一个元素
77
+ void RemoveAndAccess(std::vector<int>& vec)
78
+ {
79
+ auto prev = vec.begin();
80
+ for (auto it = vec.begin(); it != vec.end(); ++it) {
81
+ if (*it == 5) {
82
+ vec.erase(it);
83
+ int value = *prev; // 错误:prev可能也已失效
84
+ }
85
+ prev = it;
86
+ }
87
+ }
88
+
89
+ // 错误示例7:set容器erase
90
+ void RemoveSetItems(std::set<int>& set)
91
+ {
92
+ for (auto it = set.begin(); it != set.end(); ++it) {
93
+ if (*it > 100) {
94
+ set.erase(it); // 危险:迭代器失效
95
+ }
96
+ }
97
+ }
98
+
99
+ // 错误示例8:erase返回值未使用
100
+ void RemoveValues(std::vector<int>& vec)
101
+ {
102
+ for (auto it = vec.begin(); it != vec.end(); ++it) {
103
+ if (*it == 0) {
104
+ vec.erase(it); // 错误:未使用erase返回值更新迭代器
105
+ }
106
+ }
107
+ }
108
+
109
+ // 错误示例9:删除后立即访问
110
+ void RemoveAndCheck(std::list<int>& list)
111
+ {
112
+ auto it = list.begin();
113
+ while (it != list.end()) {
114
+ if (*it == 0) {
115
+ list.erase(it);
116
+ if (it != list.end()) { // 错误:it已失效
117
+ ++it;
118
+ }
119
+ } else {
120
+ ++it;
121
+ }
122
+ }
123
+ }
124
+
125
+ // 错误示例10:clear后使用迭代器
126
+ void ClearAndAccess(std::vector<int>& vec)
127
+ {
128
+ auto it = vec.begin();
129
+ vec.clear(); // 危险:所有迭代器失效
130
+ if (it != vec.end()) { // 错误:使用失效迭代器
131
+ // ...
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### ✅ 修复方案
137
+
138
+ ```cpp
139
+ // 正确示例1:使用erase返回值更新迭代器
140
+ void RemoveElements(std::vector<int>& vec)
141
+ {
142
+ for (auto it = vec.begin(); it != vec.end(); ) {
143
+ if (*it < 0) {
144
+ it = vec.erase(it); // 正确:使用返回值更新
145
+ } else {
146
+ ++it; // 正确:只在未erase时递增
147
+ }
148
+ }
149
+ }
150
+
151
+ // 正确示例2:list容器erase更新
152
+ void RemoveItems(std::list<int>& list)
153
+ {
154
+ for (auto it = list.begin(); it != list.end(); ) {
155
+ if (*it == 0) {
156
+ it = list.erase(it); // 正确:使用返回值
157
+ } else {
158
+ ++it;
159
+ }
160
+ }
161
+ }
162
+
163
+ // 正确示例3:map容器erase更新
164
+ void ProcessMap(std::map<int, std::string>& map)
165
+ {
166
+ for (auto it = map.begin(); it != map.end(); ) {
167
+ if (it->second.empty()) {
168
+ it = map.erase(it); // 正确:使用返回值
169
+ } else {
170
+ ++it;
171
+ }
172
+ }
173
+ }
174
+
175
+ // 正确示例4:使用remove_if和erase组合
176
+ void RemoveBadItems(std::vector<Item>& items)
177
+ {
178
+ items.erase(
179
+ std::remove_if(items.begin(), items.end(),
180
+ [](const Item& item) { return item.IsBad(); }),
181
+ items.end()
182
+ );
183
+ }
184
+
185
+ // 正确示例5:嵌套容器安全删除
186
+ void RemoveNested(std::vector<std::vector<int>>& data)
187
+ {
188
+ for (auto outer = data.begin(); outer != data.end(); ) {
189
+ for (auto inner = outer->begin(); inner != outer->end(); ) {
190
+ if (*inner == 0) {
191
+ inner = outer->erase(inner); // 正确:使用返回值
192
+ } else {
193
+ ++inner;
194
+ }
195
+ }
196
+ if (outer->empty()) {
197
+ outer = data.erase(outer); // 正确:使用返回值
198
+ } else {
199
+ ++outer;
200
+ }
201
+ }
202
+ }
203
+
204
+ // 正确示例6:使用索引而非迭代器
205
+ void RemoveAndAccess(std::vector<int>& vec)
206
+ {
207
+ for (size_t i = 0; i < vec.size(); ) {
208
+ if (vec[i] == 5) {
209
+ vec.erase(vec.begin() + i); // 正确:索引访问安全
210
+ } else {
211
+ ++i;
212
+ }
213
+ }
214
+ }
215
+
216
+ // 正确示例7:set容器安全删除
217
+ void RemoveSetItems(std::set<int>& set)
218
+ {
219
+ for (auto it = set.begin(); it != set.end(); ) {
220
+ if (*it > 100) {
221
+ it = set.erase(it); // 正确:使用返回值
222
+ } else {
223
+ ++it;
224
+ }
225
+ }
226
+ }
227
+
228
+ // 正确示例8:使用lambda和erase
229
+ void RemoveValues(std::vector<int>& vec)
230
+ {
231
+ vec.erase(std::remove(vec.begin(), vec.end(), 0), vec.end());
232
+ }
233
+
234
+ // 正确示例9:安全的while循环删除
235
+ void RemoveAndCheck(std::list<int>& list)
236
+ {
237
+ auto it = list.begin();
238
+ while (it != list.end()) {
239
+ if (*it == 0) {
240
+ it = list.erase(it); // 正确:使用返回值
241
+ } else {
242
+ ++it;
243
+ }
244
+ }
245
+ }
246
+
247
+ // 正确示例10:clear后重新获取迭代器
248
+ void ClearAndAccess(std::vector<int>& vec)
249
+ {
250
+ vec.clear();
251
+ auto it = vec.begin(); // 正确:clear后重新获取迭代器
252
+ if (it != vec.end()) {
253
+ // ...
254
+ }
255
+ }
256
+
257
+ // 正确示例11:使用C++11的erase返回值
258
+ template<typename Container, typename Predicate>
259
+ void RemoveIf(Container& container, Predicate pred)
260
+ {
261
+ for (auto it = container.begin(); it != container.end(); ) {
262
+ if (pred(*it)) {
263
+ it = container.erase(it);
264
+ } else {
265
+ ++it;
266
+ }
267
+ }
268
+ }
269
+ ```
270
+
271
+ ## 检测范围
272
+
273
+ 检查以下模式:
274
+
275
+ 1. `container.erase(it)` 后使用 `++it`
276
+ 2. `container.erase(it)` 后访问 `*it` 或 `it->member`
277
+ 3. erase后未更新迭代器继续遍历
278
+ 4. clear后使用旧迭代器
279
+
280
+ ## 检测要点
281
+
282
+ 1. 识别`erase`函数调用
283
+ 2. 检查erase后是否使用返回值更新迭代器
284
+ 3. 检查erase后是否继续使用原迭代器
285
+ 4. 识别`clear`后迭代器使用
286
+ 5. 排除NOPROTECT标记的代码
287
+
288
+ ## 风险流分析(RiskFlow)
289
+
290
+ - **RISK_SOURCE**: erase操作后迭代器失效
291
+ - **RISK_TYPE**: 使用失效迭代器
292
+ - **RISK_PATH**: erase -> 迭代器失效 -> 继续使用 -> 未定义行为
293
+ - **IMPACT_POINT**: 程序崩溃、内存访问错误
294
+
295
+ ## 影响分析(ImpactAnalysis)
296
+
297
+ - **Trigger**: erase后未正确更新迭代器
298
+ - **Propagation**: 失效迭代器导致内存访问错误
299
+ - **Consequence**: 程序崩溃、数据损坏、未定义行为
300
+ - **Mitigation**: 使用erase返回值更新迭代器,或使用remove_if
301
+
302
+ ## 误报排除
303
+
304
+ | 场景 | 识别特征 | 处理方式 |
305
+ |------|----------|----------|
306
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
307
+ | 使用erase返回值 | it = container.erase(it) | 不报 |
308
+ | remove_if模式 | 使用std::remove_if | 不报 |
309
+ | 重新获取迭代器 | erase后重新begin() | 不报 |
310
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
311
+ ## 测试用例
312
+
313
+ ### 触发用例(应该报)
314
+
315
+ ```cpp
316
+ // test_BoundaryCondition_008_trigger.cpp
317
+ void trigger_bad_1(std::vector<int>& vec)
318
+ {
319
+ for (auto it = vec.begin(); it != vec.end(); ++it) {
320
+ if (*it < 0) {
321
+ vec.erase(it); // 应该报:erase后++it
322
+ ++it;
323
+ }
324
+ }
325
+ }
326
+
327
+ void trigger_bad_2(std::list<int>& list)
328
+ {
329
+ for (auto it = list.begin(); it != list.end(); ++it) {
330
+ if (*it == 0) {
331
+ list.erase(it); // 应该报:erase后继续遍历
332
+ }
333
+ }
334
+ }
335
+
336
+ void trigger_bad_3(std::map<int, std::string>& map)
337
+ {
338
+ for (auto it = map.begin(); it != map.end(); ++it) {
339
+ if (it->second.empty()) {
340
+ map.erase(it);
341
+ auto key = it->first; // 应该报:访问失效迭代器
342
+ }
343
+ }
344
+ }
345
+
346
+ void trigger_bad_4(std::vector<int>& vec)
347
+ {
348
+ auto it = vec.begin();
349
+ vec.clear();
350
+ if (it != vec.end()) { // 应该报:clear后使用迭代器
351
+ // ...
352
+ }
353
+ }
354
+ ```
355
+
356
+ ### 安全用例(不应该报)
357
+
358
+ ```cpp
359
+ // test_BoundaryCondition_008_safe.cpp
360
+ void safe_good_1(std::vector<int>& vec)
361
+ {
362
+ for (auto it = vec.begin(); it != vec.end(); ) {
363
+ if (*it < 0) {
364
+ it = vec.erase(it); // 安全:使用返回值
365
+ } else {
366
+ ++it;
367
+ }
368
+ }
369
+ }
370
+
371
+ void safe_good_2(std::vector<int>& vec)
372
+ {
373
+ vec.erase(std::remove(vec.begin(), vec.end(), 0), vec.end()); // 安全:remove_if模式
374
+ }
375
+
376
+ void safe_good_3(std::set<int>& set)
377
+ {
378
+ for (auto it = set.begin(); it != set.end(); ) {
379
+ if (*it > 100) {
380
+ it = set.erase(it); // 安全:使用返回值
381
+ } else {
382
+ ++it;
383
+ }
384
+ }
385
+ }
386
+
387
+ // NOPROTECT: 特殊处理场景
388
+ void noprotect_case(std::vector<int>& vec)
389
+ {
390
+ for (auto it = vec.begin(); it != vec.end(); ++it) {
391
+ vec.erase(it);
392
+ }
393
+ }
394
+ ```