@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,425 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_009"
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:int到size_t转换
22
+ void AllocateBuffer(int size)
23
+ {
24
+ size_t bufferSize = size; // 危险:size为负数时转换错误
25
+ char* buffer = new char[bufferSize];
26
+ }
27
+
28
+ // 错误示例2:int64到int32截断
29
+ void StoreValue(int64_t largeValue)
30
+ {
31
+ int32_t smallValue = static_cast<int32_t>(largeValue); // 危险:可能截断
32
+ data_.push_back(smallValue);
33
+ }
34
+
35
+ // 错误示例3:uint32到int32转换
36
+ void ProcessUnsigned(uint32_t unsignedValue)
37
+ {
38
+ int32_t signedValue = static_cast<int32_t>(unsignedValue); // 危险:可能溢出
39
+ array_[signedValue] = 100; // 可能越界
40
+ }
41
+
42
+ // 错误示例4:Parcel数据直接转换
43
+ int GetArrayIndex(Parcel& parcel)
44
+ {
45
+ int64_t value = parcel.ReadInt64();
46
+ int index = static_cast<int>(value); // 危险:截断和范围问题
47
+ return index;
48
+ }
49
+
50
+ // 错误示例5:size_t到int转换
51
+ int CalculatePosition(size_t pos)
52
+ {
53
+ int position = static_cast<int>(pos); // 危险:pos可能超过INT_MAX
54
+ return position;
55
+ }
56
+
57
+ // 错误示例6:浮点到整数转换
58
+ void ConvertCoordinate(double coordinate)
59
+ {
60
+ int intCoord = static_cast<int>(coordinate); // 危险:可能溢出
61
+ positions_[intCoord] = 1;
62
+ }
63
+
64
+ // 错误示例7:乘法溢出
65
+ int CalculateTotal(int base, int multiplier)
66
+ {
67
+ return base * multiplier; // 危险:可能溢出
68
+ }
69
+
70
+ // 错误示例8:加法溢出
71
+ int IncrementCounter(int current, int increment)
72
+ {
73
+ return current + increment; // 危险:可能溢出
74
+ }
75
+
76
+ // 错误示例9:负数取模
77
+ int ComputeHash(int key, int tableSize)
78
+ {
79
+ return key % tableSize; // 危险:key为负数时结果可能为负
80
+ }
81
+
82
+ // 错误示例10:隐式转换
83
+ void SetSize(unsigned int size)
84
+ {
85
+ int actualSize = size; // 危险:隐式转换,可能溢出
86
+ buffer_.resize(actualSize);
87
+ }
88
+
89
+ // 错误示例11:表达式溢出
90
+ int CalculateIndex(int x, int y, int z)
91
+ {
92
+ return x * y + z; // 危险:x*y可能溢出
93
+ }
94
+
95
+ // 错误示例12:long到int转换
96
+ void ProcessLongValue(long value)
97
+ {
98
+ int intValue = value; // 危险:隐式截断
99
+ DoSomething(intValue);
100
+ }
101
+ ```
102
+
103
+ ### ✅ 修复方案
104
+
105
+ ```cpp
106
+ // 正确示例1:检查范围后转换
107
+ void AllocateBuffer(int size)
108
+ {
109
+ if (size < 0 || size > MAX_BUFFER_SIZE) {
110
+ LOGE("Invalid buffer size: %d", size);
111
+ return;
112
+ }
113
+ size_t bufferSize = static_cast<size_t>(size); // 正确:已验证
114
+ char* buffer = new char[bufferSize];
115
+ }
116
+
117
+ // 正确示例2:检查截断范围
118
+ void StoreValue(int64_t largeValue)
119
+ {
120
+ if (largeValue < INT32_MIN || largeValue > INT32_MAX) {
121
+ LOGE("Value out of int32 range: %lld", largeValue);
122
+ return;
123
+ }
124
+ int32_t smallValue = static_cast<int32_t>(largeValue); // 正确:已验证
125
+ data_.push_back(smallValue);
126
+ }
127
+
128
+ // 正确示例3:unsigned到signed转换检查
129
+ void ProcessUnsigned(uint32_t unsignedValue)
130
+ {
131
+ if (unsignedValue > INT32_MAX) {
132
+ LOGE("Value too large: %u", unsignedValue);
133
+ return;
134
+ }
135
+ int32_t signedValue = static_cast<int32_t>(unsignedValue); // 正确:已验证
136
+ array_[signedValue] = 100;
137
+ }
138
+
139
+ // 正确示例4:安全的Parcel数据转换
140
+ int GetArrayIndex(Parcel& parcel)
141
+ {
142
+ int64_t value = parcel.ReadInt64();
143
+ if (value < 0 || value > INT_MAX) {
144
+ LOGE("Invalid index from parcel: %lld", value);
145
+ return -1;
146
+ }
147
+ return static_cast<int>(value); // 正确:已验证
148
+ }
149
+
150
+ // 正确示例5:size_t到int安全转换
151
+ int CalculatePosition(size_t pos)
152
+ {
153
+ if (pos > INT_MAX) {
154
+ LOGE("Position too large: %zu", pos);
155
+ return -1;
156
+ }
157
+ return static_cast<int>(pos); // 正确:已验证
158
+ }
159
+
160
+ // 正确示例6:浮点到整数安全转换
161
+ void ConvertCoordinate(double coordinate)
162
+ {
163
+ if (coordinate < INT_MIN || coordinate > INT_MAX) {
164
+ LOGE("Coordinate out of range: %f", coordinate);
165
+ return;
166
+ }
167
+ int intCoord = static_cast<int>(coordinate); // 正确:已验证
168
+ if (intCoord >= 0 && intCoord < MAX_POSITIONS) {
169
+ positions_[intCoord] = 1;
170
+ }
171
+ }
172
+
173
+ // 正确示例7:使用安全乘法
174
+ int CalculateTotal(int base, int multiplier)
175
+ {
176
+ if (base > 0 && multiplier > INT_MAX / base) {
177
+ LOGE("Multiplication overflow");
178
+ return INT_MAX;
179
+ }
180
+ if (base < 0 && multiplier < INT_MAX / base) {
181
+ LOGE("Multiplication overflow");
182
+ return INT_MIN;
183
+ }
184
+ return base * multiplier; // 正确:已验证
185
+ }
186
+
187
+ // 正确示例8:安全加法
188
+ int IncrementCounter(int current, int increment)
189
+ {
190
+ if (increment > 0 && current > INT_MAX - increment) {
191
+ LOGE("Addition overflow");
192
+ return INT_MAX;
193
+ }
194
+ if (increment < 0 && current < INT_MIN - increment) {
195
+ LOGE("Addition underflow");
196
+ return INT_MIN;
197
+ }
198
+ return current + increment; // 正确:已验证
199
+ }
200
+
201
+ // 正确示例9:安全的哈希计算
202
+ int ComputeHash(int key, int tableSize)
203
+ {
204
+ int hash = key % tableSize;
205
+ if (hash < 0) { // 正确:处理负数结果
206
+ hash += tableSize;
207
+ }
208
+ return hash;
209
+ }
210
+
211
+ // 正确示例10:安全的隐式转换
212
+ void SetSize(unsigned int size)
213
+ {
214
+ if (size > INT_MAX) {
215
+ LOGE("Size too large: %u", size);
216
+ return;
217
+ }
218
+ int actualSize = static_cast<int>(size); // 正确:已验证
219
+ buffer_.resize(actualSize);
220
+ }
221
+
222
+ // 正确示例11:表达式溢出检查
223
+ int CalculateIndex(int x, int y, int z)
224
+ {
225
+ // 先检查乘法
226
+ if (x != 0 && y != 0) {
227
+ if (x > 0 && y > INT_MAX / x) {
228
+ LOGE("Multiplication overflow");
229
+ return -1;
230
+ }
231
+ if (x > 0 && y < INT_MIN / x) {
232
+ LOGE("Multiplication underflow");
233
+ return -1;
234
+ }
235
+ if (x < 0 && y > INT_MIN / x) {
236
+ LOGE("Multiplication overflow");
237
+ return -1;
238
+ }
239
+ if (x < 0 && y < INT_MAX / x) {
240
+ LOGE("Multiplication underflow");
241
+ return -1;
242
+ }
243
+ }
244
+ int product = x * y;
245
+
246
+ // 再检查加法
247
+ if (z > 0 && product > INT_MAX - z) {
248
+ LOGE("Addition overflow");
249
+ return -1;
250
+ }
251
+ if (z < 0 && product < INT_MIN - z) {
252
+ LOGE("Addition underflow");
253
+ return -1;
254
+ }
255
+ return product + z; // 正确:已验证
256
+ }
257
+
258
+ // 正确示例12:使用辅助函数
259
+ template<typename DestType, typename SrcType>
260
+ bool SafeCast(SrcType src, DestType& dest)
261
+ {
262
+ if (src > static_cast<SrcType>(std::numeric_limits<DestType>::max()) ||
263
+ src < static_cast<SrcType>(std::numeric_limits<DestType>::lowest())) {
264
+ return false;
265
+ }
266
+ dest = static_cast<DestType>(src);
267
+ return true;
268
+ }
269
+
270
+ void ProcessLongValue(long value)
271
+ {
272
+ int intValue;
273
+ if (!SafeCast(value, intValue)) { // 正确:使用辅助函数
274
+ LOGE("Value out of int range: %ld", value);
275
+ return;
276
+ }
277
+ DoSomething(intValue);
278
+ }
279
+
280
+ // 正确示例13:使用标准库安全整数运算
281
+ #include <limits>
282
+
283
+ int SafeMultiply(int a, int b)
284
+ {
285
+ if (a == 0 || b == 0) return 0;
286
+ if (a > 0) {
287
+ if (b > 0 && a > std::numeric_limits<int>::max() / b) {
288
+ throw std::overflow_error("Multiplication overflow");
289
+ }
290
+ if (b < 0 && b < std::numeric_limits<int>::min() / a) {
291
+ throw std::overflow_error("Multiplication underflow");
292
+ }
293
+ } else {
294
+ if (b > 0 && a < std::numeric_limits<int>::min() / b) {
295
+ throw std::overflow_error("Multiplication underflow");
296
+ }
297
+ if (b < 0 && a < std::numeric_limits<int>::max() / b) {
298
+ throw std::overflow_error("Multiplication overflow");
299
+ }
300
+ }
301
+ return a * b;
302
+ }
303
+ ```
304
+
305
+ ## 检测范围
306
+
307
+ 检查以下模式:
308
+
309
+ 1. `static_cast<Type>(value)` - 显式类型转换
310
+ 2. `Type value = srcValue` - 隐式类型转换
311
+ 3. `(Type)value` - C风格转换
312
+ 4. 整数运算:`*`, `+`, `-` 可能溢出
313
+ 5. 浮点到整数转换
314
+
315
+ ## 检测要点
316
+
317
+ 1. 识别类型转换操作
318
+ 2. 检查源类型和目标类型的范围
319
+ 3. 识别外部输入数据来源(参数、Parcel、用户输入)
320
+ 4. 检查是否进行了范围检查
321
+ 5. 排除NOPROTECT标记的代码
322
+
323
+ ## 风险流分析(RiskFlow)
324
+
325
+ - **RISK_SOURCE**: 外部输入数据
326
+ - **RISK_TYPE**: 整数溢出/截断
327
+ - **RISK_PATH**: 类型转换 -> 数据截断/溢出 -> 程序错误
328
+ - **IMPACT_POINT**: 数组越界、内存错误、逻辑错误
329
+
330
+ ## 影响分析(ImpactAnalysis)
331
+
332
+ - **Trigger**: 不安全的类型转换或整数运算
333
+ - **Propagation**: 数据截断导致后续计算错误
334
+ - **Consequence**: 数组越界、缓冲区溢出、程序崩溃
335
+ - **Mitigation**: 转换前检查范围,使用安全运算函数
336
+
337
+ ## 误报排除
338
+
339
+ | 场景 | 识别特征 | 处理方式 |
340
+ |------|----------|----------|
341
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
342
+ | 已有范围检查 | 存在数值范围判断 | 不报 |
343
+ | 安全类型 | 同类型或更大范围转换 | 不报 |
344
+ | 常量转换 | 转换常量值 | 不报 |
345
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
346
+ ## 测试用例
347
+
348
+ ### 触发用例(应该报)
349
+
350
+ ```cpp
351
+ // test_BoundaryCondition_009_trigger.cpp
352
+ void trigger_bad_1(int size)
353
+ {
354
+ size_t bufferSize = size; // 应该报:int到size_t无检查
355
+ char* buffer = new char[bufferSize];
356
+ }
357
+
358
+ void trigger_bad_2(int64_t value)
359
+ {
360
+ int32_t small = static_cast<int32_t>(value); // 应该报:截断无检查
361
+ }
362
+
363
+ void trigger_bad_3(Parcel& parcel)
364
+ {
365
+ uint32_t value = parcel.ReadUint32();
366
+ int32_t signedValue = static_cast<int32_t>(value); // 应该报:无范围检查
367
+ }
368
+
369
+ int trigger_bad_4(int a, int b)
370
+ {
371
+ return a * b; // 应该报:乘法可能溢出
372
+ }
373
+
374
+ int trigger_bad_5(int current, int increment)
375
+ {
376
+ return current + increment; // 应该报:加法可能溢出
377
+ }
378
+
379
+ void trigger_bad_6(double coord)
380
+ {
381
+ int intCoord = static_cast<int>(coord); // 应该报:浮点到整数无检查
382
+ }
383
+ ```
384
+
385
+ ### 安全用例(不应该报)
386
+
387
+ ```cpp
388
+ // test_BoundaryCondition_009_safe.cpp
389
+ void safe_good_1(int size)
390
+ {
391
+ if (size < 0 || size > MAX_SIZE) { // 安全:有范围检查
392
+ return;
393
+ }
394
+ size_t bufferSize = static_cast<size_t>(size);
395
+ char* buffer = new char[bufferSize];
396
+ }
397
+
398
+ void safe_good_2(int64_t value)
399
+ {
400
+ if (value >= INT32_MIN && value <= INT32_MAX) { // 安全:有范围检查
401
+ int32_t small = static_cast<int32_t>(value);
402
+ }
403
+ }
404
+
405
+ int safe_good_3(int a, int b)
406
+ {
407
+ if (a > 0 && b > INT_MAX / a) { // 安全:有溢出检查
408
+ return INT_MAX;
409
+ }
410
+ return a * b;
411
+ }
412
+
413
+ void safe_good_4(double coord)
414
+ {
415
+ if (coord >= INT_MIN && coord <= INT_MAX) { // 安全:有范围检查
416
+ int intCoord = static_cast<int>(coord);
417
+ }
418
+ }
419
+
420
+ // NOPROTECT: 特殊处理场景
421
+ void noprotect_case(int64_t value)
422
+ {
423
+ int32_t small = static_cast<int32_t>(value);
424
+ }
425
+ ```