@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,432 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_007"
3
+ name: "Parcel序列化和反序列化必须匹配"
4
+ category: "边界条件"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # Parcel序列化和反序列化必须匹配
11
+
12
+ ## 问题描述
13
+
14
+ Parcel的序列化和反序列化必须完全匹配,包括顺序、类型和数量。不匹配的序列化/反序列化会导致数据错误、内存越界读取或程序崩溃。
15
+
16
+ ## 检测示例
17
+
18
+ ### ❌ 问题代码
19
+
20
+ ```cpp
21
+ // 错误示例1:顺序不匹配
22
+ // 序列化
23
+ void WriteData(Parcel& parcel)
24
+ {
25
+ parcel.WriteInt32(count); // 1. 写入count
26
+ parcel.WriteString(name); // 2. 写入name
27
+ parcel.WriteBool(enabled); // 3. 写入enabled
28
+ }
29
+
30
+ // 反序列化 - 顺序错误
31
+ void ReadData(Parcel& parcel)
32
+ {
33
+ enabled = parcel.ReadBool(); // 错误:先读Bool,但实际是Int32
34
+ name = parcel.ReadString(); // 错误:读取顺序不匹配
35
+ count = parcel.ReadInt32(); // 错误:顺序不匹配
36
+ }
37
+
38
+ // 错误示例2:类型不匹配
39
+ // 序列化
40
+ void Serialize(Packet& packet)
41
+ {
42
+ parcel.WriteUint32(id);
43
+ parcel.WriteFloat(value);
44
+ }
45
+
46
+ // 反序列化 - 类型错误
47
+ void Deserialize(Packet& packet)
48
+ {
49
+ id = parcel.ReadInt32(); // 错误:Uint32用Int32读取
50
+ value = parcel.ReadDouble(); // 错误:Float用Double读取
51
+ }
52
+
53
+ // 错误示例3:数量不匹配(多读)
54
+ // 序列化
55
+ void Save(Parcel& parcel)
56
+ {
57
+ parcel.WriteInt32(a);
58
+ parcel.WriteInt32(b);
59
+ }
60
+
61
+ // 反序列化 - 多读
62
+ void Load(Parcel& parcel)
63
+ {
64
+ a = parcel.ReadInt32();
65
+ b = parcel.ReadInt32();
66
+ c = parcel.ReadInt32(); // 错误:多读了一个,越界读取
67
+ }
68
+
69
+ // 错误示例4:数量不匹配(少读)
70
+ // 序列化
71
+ void Store(Parcel& parcel)
72
+ {
73
+ parcel.WriteInt32(x);
74
+ parcel.WriteInt32(y);
75
+ parcel.WriteInt32(z);
76
+ }
77
+
78
+ // 反序列化 - 少读
79
+ void Restore(Parcel& parcel)
80
+ {
81
+ x = parcel.ReadInt32();
82
+ y = parcel.ReadInt32();
83
+ // 错误:少读了z,可能导致后续读取错误
84
+ }
85
+
86
+ // 错误示例5:条件字段不匹配
87
+ // 序列化
88
+ void SerializeData(Parcel& parcel, const Data& data)
89
+ {
90
+ parcel.WriteBool(data.hasExtra);
91
+ parcel.WriteInt32(data.value);
92
+ if (data.hasExtra) {
93
+ parcel.WriteString(data.extra);
94
+ }
95
+ }
96
+
97
+ // 反序列化 - 条件不匹配
98
+ void DeserializeData(Parcel& parcel, Data& data)
99
+ {
100
+ data.hasExtra = parcel.ReadBool();
101
+ data.value = parcel.ReadInt32();
102
+ data.extra = parcel.ReadString(); // 错误:无条件读取,hasExtra为false时越界
103
+ }
104
+
105
+ // 错误示例6:数组处理不匹配
106
+ // 序列化
107
+ void SerializeArray(Parcel& parcel, const std::vector<int>& arr)
108
+ {
109
+ parcel.WriteUint32(arr.size());
110
+ for (int val : arr) {
111
+ parcel.WriteInt32(val);
112
+ }
113
+ }
114
+
115
+ // 反序列化 - 数量不匹配
116
+ void DeserializeArray(Parcel& parcel, std::vector<int>& arr)
117
+ {
118
+ uint32_t count = parcel.ReadUint32();
119
+ for (uint32_t i = 0; i < count + 1; i++) { // 错误:多读一个
120
+ arr.push_back(parcel.ReadInt32());
121
+ }
122
+ }
123
+
124
+ // 错误示例7:版本兼容问题
125
+ // 旧版本序列化
126
+ void SerializeV1(Parcel& parcel)
127
+ {
128
+ parcel.WriteInt32(version);
129
+ parcel.WriteString(name);
130
+ }
131
+
132
+ // 新版本反序列化 - 期望更多字段
133
+ void DeserializeV2(Parcel& parcel)
134
+ {
135
+ int version = parcel.ReadInt32();
136
+ std::string name = parcel.ReadString();
137
+ std::string extra = parcel.ReadString(); // 错误:V1没有这个字段
138
+ }
139
+ ```
140
+
141
+ ### ✅ 修复方案
142
+
143
+ ```cpp
144
+ // 正确示例1:顺序匹配
145
+ // 序列化
146
+ void WriteData(Parcel& parcel)
147
+ {
148
+ parcel.WriteInt32(count);
149
+ parcel.WriteString(name);
150
+ parcel.WriteBool(enabled);
151
+ }
152
+
153
+ // 反序列化 - 顺序正确
154
+ void ReadData(Parcel& parcel)
155
+ {
156
+ count = parcel.ReadInt32(); // 1. 读取count
157
+ name = parcel.ReadString(); // 2. 读取name
158
+ enabled = parcel.ReadBool(); // 3. 读取enabled
159
+ }
160
+
161
+ // 正确示例2:类型匹配
162
+ // 序列化
163
+ void Serialize(Packet& packet)
164
+ {
165
+ parcel.WriteUint32(id);
166
+ parcel.WriteFloat(value);
167
+ }
168
+
169
+ // 反序列化 - 类型正确
170
+ void Deserialize(Packet& packet)
171
+ {
172
+ id = parcel.ReadUint32(); // 正确:Uint32匹配
173
+ value = parcel.ReadFloat(); // 正确:Float匹配
174
+ }
175
+
176
+ // 正确示例3:数量匹配
177
+ // 序列化
178
+ void Save(Parcel& parcel)
179
+ {
180
+ parcel.WriteInt32(a);
181
+ parcel.WriteInt32(b);
182
+ }
183
+
184
+ // 反序列化 - 数量正确
185
+ void Load(Parcel& parcel)
186
+ {
187
+ a = parcel.ReadInt32();
188
+ b = parcel.ReadInt32();
189
+ // 数量完全匹配
190
+ }
191
+
192
+ // 正确示例4:条件字段匹配
193
+ // 序列化
194
+ void SerializeData(Parcel& parcel, const Data& data)
195
+ {
196
+ parcel.WriteBool(data.hasExtra);
197
+ parcel.WriteInt32(data.value);
198
+ if (data.hasExtra) {
199
+ parcel.WriteString(data.extra);
200
+ }
201
+ }
202
+
203
+ // 反序列化 - 条件匹配
204
+ void DeserializeData(Parcel& parcel, Data& data)
205
+ {
206
+ data.hasExtra = parcel.ReadBool();
207
+ data.value = parcel.ReadInt32();
208
+ if (data.hasExtra) { // 正确:条件匹配
209
+ data.extra = parcel.ReadString();
210
+ }
211
+ }
212
+
213
+ // 正确示例5:数组处理匹配
214
+ // 序列化
215
+ void SerializeArray(Parcel& parcel, const std::vector<int>& arr)
216
+ {
217
+ parcel.WriteUint32(arr.size());
218
+ for (int val : arr) {
219
+ parcel.WriteInt32(val);
220
+ }
221
+ }
222
+
223
+ // 反序列化 - 数量正确
224
+ void DeserializeArray(Parcel& parcel, std::vector<int>& arr)
225
+ {
226
+ uint32_t count = parcel.ReadUint32();
227
+ if (count > MAX_ARRAY_SIZE) { // 安全检查
228
+ LOGE("Invalid array count");
229
+ return;
230
+ }
231
+ for (uint32_t i = 0; i < count; i++) { // 正确:数量匹配
232
+ arr.push_back(parcel.ReadInt32());
233
+ }
234
+ }
235
+
236
+ // 正确示例6:版本兼容处理
237
+ // 序列化 - 包含版本号
238
+ void SerializeV2(Parcel& parcel)
239
+ {
240
+ parcel.WriteInt32(2); // version
241
+ parcel.WriteString(name);
242
+ parcel.WriteString(extra); // V2新增字段
243
+ }
244
+
245
+ // 反序列化 - 版本兼容
246
+ void Deserialize(Parcel& parcel)
247
+ {
248
+ int version = parcel.ReadInt32();
249
+ std::string name = parcel.ReadString();
250
+ std::string extra = "";
251
+ if (version >= 2) { // 正确:根据版本处理
252
+ extra = parcel.ReadString();
253
+ }
254
+ }
255
+
256
+ // 正确示例7:使用统一的结构体方法
257
+ struct PacketData {
258
+ int32_t count;
259
+ std::string name;
260
+ bool enabled;
261
+
262
+ void Marshal(Parcel& parcel) const {
263
+ parcel.WriteInt32(count);
264
+ parcel.WriteString(name);
265
+ parcel.WriteBool(enabled);
266
+ }
267
+
268
+ void Unmarshal(Parcel& parcel) {
269
+ count = parcel.ReadInt32();
270
+ name = parcel.ReadString();
271
+ enabled = parcel.ReadBool();
272
+ }
273
+ };
274
+
275
+ // 正确示例8:使用辅助工具确保匹配
276
+ class ParcelHelper {
277
+ public:
278
+ template<typename T>
279
+ static void Write(Parcel& parcel, const T& value) {
280
+ parcel.WriteParcelable(value);
281
+ }
282
+
283
+ template<typename T>
284
+ static bool Read(Parcel& parcel, T& value) {
285
+ return parcel.ReadParcelable(&value);
286
+ }
287
+ };
288
+ ```
289
+
290
+ ## 检测范围
291
+
292
+ 检查以下模式:
293
+
294
+ 1. 同一类的序列化和反序列化函数
295
+ 2. `Write`/`Read`函数对
296
+ 3. `Serialize`/`Deserialize`函数对
297
+ 4. `Marshal`/`Unmarshal`函数对
298
+ 5. `Save`/`Load`函数对
299
+
300
+ ## 检测要点
301
+
302
+ 1. 识别序列化和反序列化函数对
303
+ 2. 比较`Write*`和`Read*`的调用顺序
304
+ 3. 比较`Write*`和`Read*`的类型
305
+ 4. 比较`Write*`和`Read*`的数量
306
+ 5. 检查条件字段的处理是否一致
307
+ 6. 排除NOPROTECT标记的代码
308
+
309
+ ## 风险流分析(RiskFlow)
310
+
311
+ - **RISK_SOURCE**: 序列化/反序列化函数不匹配
312
+ - **RISK_TYPE**: 数据解析错误
313
+ - **RISK_PATH**: 不匹配操作 -> 数据错误/越界读取 -> 程序崩溃
314
+ - **IMPACT_POINT**: 数据完整性、程序稳定性
315
+
316
+ ## 影响分析(ImpactAnalysis)
317
+
318
+ - **Trigger**: 序列化与反序列化不匹配
319
+ - **Propagation**: 数据读取错误导致后续解析失败
320
+ - **Consequence**: 数据损坏、越界读取、程序崩溃
321
+ - **Mitigation**: 确保Write/Read顺序、类型、数量完全匹配
322
+
323
+ ## 误报排除
324
+
325
+ | 场景 | 识别特征 | 处理方式 |
326
+ |------|----------|----------|
327
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
328
+ | 版本兼容处理 | 有版本号判断逻辑 | 不报 |
329
+ | 条件分支一致 | Write和Read都有相同条件 | 不报 |
330
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
331
+ ## 测试用例
332
+
333
+ ### 触发用例(应该报)
334
+
335
+ ```cpp
336
+ // test_BoundaryCondition_007_trigger.cpp
337
+ // 序列化
338
+ void TriggerBad1Write(Parcel& parcel)
339
+ {
340
+ parcel.WriteInt32(count);
341
+ parcel.WriteString(name);
342
+ }
343
+
344
+ // 反序列化 - 顺序错误
345
+ void TriggerBad1Read(Parcel& parcel)
346
+ {
347
+ name = parcel.ReadString(); // 应该报:顺序不匹配
348
+ count = parcel.ReadInt32();
349
+ }
350
+
351
+ // 序列化
352
+ void TriggerBad2Write(Parcel& parcel)
353
+ {
354
+ parcel.WriteInt32(a);
355
+ parcel.WriteInt32(b);
356
+ }
357
+
358
+ // 反序列化 - 多读
359
+ void TriggerBad2Read(Parcel& parcel)
360
+ {
361
+ a = parcel.ReadInt32();
362
+ b = parcel.ReadInt32();
363
+ c = parcel.ReadInt32(); // 应该报:数量不匹配
364
+ }
365
+
366
+ // 序列化
367
+ void TriggerBad3Write(Parcel& parcel)
368
+ {
369
+ parcel.WriteBool(hasData);
370
+ if (hasData) {
371
+ parcel.WriteString(data);
372
+ }
373
+ }
374
+
375
+ // 反序列化 - 条件不匹配
376
+ void TriggerBad3Read(Parcel& parcel)
377
+ {
378
+ hasData = parcel.ReadBool();
379
+ data = parcel.ReadString(); // 应该报:无条件读取
380
+ }
381
+ ```
382
+
383
+ ### 安全用例(不应该报)
384
+
385
+ ```cpp
386
+ // test_BoundaryCondition_007_safe.cpp
387
+ // 序列化
388
+ void SafeGood1Write(Parcel& parcel)
389
+ {
390
+ parcel.WriteInt32(count);
391
+ parcel.WriteString(name);
392
+ parcel.WriteBool(enabled);
393
+ }
394
+
395
+ // 反序列化 - 完全匹配
396
+ void SafeGood1Read(Parcel& parcel)
397
+ {
398
+ count = parcel.ReadInt32();
399
+ name = parcel.ReadString();
400
+ enabled = parcel.ReadBool();
401
+ }
402
+
403
+ // 序列化
404
+ void SafeGood2Write(Parcel& parcel)
405
+ {
406
+ parcel.WriteBool(hasData);
407
+ if (hasData) {
408
+ parcel.WriteString(data);
409
+ }
410
+ }
411
+
412
+ // 反序列化 - 条件匹配
413
+ void SafeGood2Read(Parcel& parcel)
414
+ {
415
+ hasData = parcel.ReadBool();
416
+ if (hasData) { // 安全:条件匹配
417
+ data = parcel.ReadString();
418
+ }
419
+ }
420
+
421
+ // NOPROTECT: 特殊处理场景
422
+ void noprotect_write(Parcel& parcel)
423
+ {
424
+ parcel.WriteInt32(a);
425
+ }
426
+
427
+ void noprotect_read(Parcel& parcel)
428
+ {
429
+ a = parcel.ReadInt32();
430
+ b = parcel.ReadInt32();
431
+ }
432
+ ```