@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
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@ohos-graphics/stability-code-review",
3
+ "version": "0.1.0",
4
+ "description": "OpenHarmony C/C++ stability code review skill library for opencode/Codex agents.",
5
+ "type": "module",
6
+ "bin": {
7
+ "ohos-stability-skill": "bin/install.js"
8
+ },
9
+ "scripts": {
10
+ "test": "node --test"
11
+ },
12
+ "files": [
13
+ "SKILL.md",
14
+ "README.md",
15
+ "config/",
16
+ "references/",
17
+ "scripts/",
18
+ "bin/"
19
+ ],
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://gitcode.com/OH-Graphics-Stability/stability-code-review.git"
26
+ },
27
+ "keywords": [
28
+ "opencode",
29
+ "codex",
30
+ "skill",
31
+ "openharmony",
32
+ "cpp",
33
+ "stability",
34
+ "code-review"
35
+ ],
36
+ "license": "Apache-2.0",
37
+ "engines": {
38
+ "node": ">=18"
39
+ }
40
+ }
@@ -0,0 +1,275 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_001"
3
+ name: "Parcel数据不可作为循环或递归条件"
4
+ category: "边界条件"
5
+ severity: "CRITICAL"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # Parcel数据不可作为循环或递归条件
11
+
12
+ ## 问题描述
13
+
14
+ 从Parcel中读取的数据不可信,不能直接作为循环或递归的条件,必须进行上限保护处理。恶意构造的Parcel数据可能包含超大数值,导致死循环、栈溢出或拒绝服务攻击。
15
+
16
+ ## 检测示例
17
+
18
+ ### ❌ 问题代码
19
+
20
+ ```cpp
21
+ // 错误示例1:Parcel数据直接作为循环条件
22
+ void ReadDataFromParcel(Parcel& parcel)
23
+ {
24
+ int count = parcel.ReadInt32(); // 不可信数据
25
+ for (int i = 0; i < count; i++) { // 危险:count可能为超大值
26
+ ProcessItem(parcel);
27
+ }
28
+ }
29
+
30
+ // 错误示例2:Parcel数据作为递归深度
31
+ void ProcessNestedData(Parcel& parcel, int depth)
32
+ {
33
+ if (depth <= 0) return;
34
+ int count = parcel.ReadInt32();
35
+ for (int i = 0; i < count; i++) { // 嵌套循环,可能深度爆炸
36
+ ProcessNestedData(parcel, depth - 1);
37
+ }
38
+ }
39
+
40
+ // 错误示例3:while循环使用Parcel数据
41
+ void ReadMessages(Parcel& parcel)
42
+ {
43
+ int32_t msgCount = parcel.ReadInt32();
44
+ while (msgCount > 0) { // 危险:msgCount可能为负数或超大值
45
+ ProcessMessage(parcel);
46
+ msgCount--;
47
+ }
48
+ }
49
+
50
+ // 错误示例4:递归函数使用Parcel数据作为终止条件
51
+ struct TreeNode {
52
+ int value;
53
+ std::vector<TreeNode*> children;
54
+ };
55
+
56
+ TreeNode* BuildTree(Parcel& parcel)
57
+ {
58
+ int childCount = parcel.ReadInt32(); // 不可信数据
59
+ TreeNode* node = new TreeNode();
60
+ for (int i = 0; i < childCount; i++) { // 危险:可能构造超大树
61
+ node->children.push_back(BuildTree(parcel)); // 递归深度不可控
62
+ }
63
+ return node;
64
+ }
65
+ ```
66
+
67
+ ### ✅ 修复方案
68
+
69
+ ```cpp
70
+ // 正确示例1:添加上限保护(实际代码中的动态上限)
71
+ void ReadDataFromParcel(Parcel& parcel)
72
+ {
73
+ int32_t commandSize = 0;
74
+ // 关键:先检查Parcel读取是否成功
75
+ if (!parcel.ReadInt32(commandSize)) {
76
+ ROSEN_LOGE("cannot read commandSize");
77
+ return false;
78
+ }
79
+
80
+ // 关键:使用动态上限而非仅常量上限
81
+ size_t readableSize = parcel.GetReadableBytes();
82
+ size_t len = static_cast<size_t>(commandSize);
83
+
84
+ // 多重检查:动态上限 + 容器上限
85
+ if (len > readableSize || len > payload_.max_size()) {
86
+ ROSEN_LOGE("Failed read vector, size:%zu, readAbleSize:%zu", len, readableSize);
87
+ return false;
88
+ }
89
+
90
+ for (size_t i = 0; i < len; i++) { // 安全:已校验len不超过readableSize
91
+ ProcessItem(parcel);
92
+ }
93
+ }
94
+
95
+ // 正确示例1b:常量上限保护(适用于简单场景)
96
+ constexpr int MAX_ITEM_COUNT = 1000;
97
+
98
+ void ReadSimpleData(Parcel& parcel)
99
+ {
100
+ int count = parcel.ReadInt32();
101
+ if (count < 0 || count > MAX_ITEM_COUNT) { // 常量上限
102
+ LOGE("Invalid count: %d, max allowed: %d", count, MAX_ITEM_COUNT);
103
+ return;
104
+ }
105
+ for (int i = 0; i < count; i++) {
106
+ ProcessItem(parcel);
107
+ }
108
+ }
109
+
110
+ // 正确示例2:递归深度限制
111
+ constexpr int MAX_RECURSION_DEPTH = 10;
112
+ constexpr int MAX_CHILD_COUNT = 100;
113
+
114
+ void ProcessNestedData(Parcel& parcel, int depth)
115
+ {
116
+ if (depth <= 0 || depth > MAX_RECURSION_DEPTH) {
117
+ LOGE("Invalid recursion depth: %d", depth);
118
+ return;
119
+ }
120
+ int count = parcel.ReadInt32();
121
+ if (count < 0 || count > MAX_CHILD_COUNT) {
122
+ LOGE("Invalid count: %d", count);
123
+ return;
124
+ }
125
+ for (int i = 0; i < count; i++) {
126
+ ProcessNestedData(parcel, depth - 1);
127
+ }
128
+ }
129
+
130
+ // 正确示例3:使用安全的循环控制
131
+ constexpr int32_t MAX_MESSAGE_COUNT = 500;
132
+
133
+ void ReadMessages(Parcel& parcel)
134
+ {
135
+ int32_t msgCount = parcel.ReadInt32();
136
+ if (msgCount < 0 || msgCount > MAX_MESSAGE_COUNT) {
137
+ LOGE("Invalid message count: %d", msgCount);
138
+ return;
139
+ }
140
+ for (int32_t i = 0; i < msgCount; i++) {
141
+ ProcessMessage(parcel);
142
+ }
143
+ }
144
+
145
+ // 正确示例4:限制树结构和递归深度
146
+ constexpr int MAX_TREE_DEPTH = 8;
147
+ constexpr int MAX_TREE_CHILDREN = 20;
148
+
149
+ TreeNode* BuildTree(Parcel& parcel, int currentDepth)
150
+ {
151
+ if (currentDepth > MAX_TREE_DEPTH) {
152
+ LOGE("Tree depth exceeded: %d", currentDepth);
153
+ return nullptr;
154
+ }
155
+ int childCount = parcel.ReadInt32();
156
+ if (childCount < 0 || childCount > MAX_TREE_CHILDREN) {
157
+ LOGE("Invalid child count: %d", childCount);
158
+ return nullptr;
159
+ }
160
+ TreeNode* node = new TreeNode();
161
+ for (int i = 0; i < childCount; i++) {
162
+ TreeNode* child = BuildTree(parcel, currentDepth + 1);
163
+ if (child != nullptr) {
164
+ node->children.push_back(child);
165
+ }
166
+ }
167
+ return node;
168
+ }
169
+ ```
170
+
171
+ ## 检测范围
172
+
173
+ 检查以下模式:
174
+
175
+ 1. 从Parcel读取数据后直接用于`for`循环
176
+ 2. 从Parcel读取数据后直接用于`while`循环
177
+ 3. 从Parcel读取数据后直接用于递归终止条件
178
+ 4. 从Parcel读取数据后用于嵌套循环控制
179
+
180
+ ## 检测要点
181
+
182
+ 1. 识别Parcel读取函数:`ReadInt32`, `ReadInt64`, `ReadUint32`, `ReadUint64`等
183
+ 2. 跟踪读取的变量是否用于循环条件
184
+ 3. 检查是否进行了上限保护
185
+ 4. 检查递归函数是否限制递归深度
186
+ 5. 排除NOPROTECT标记的代码
187
+
188
+ ## 风险流分析(RiskFlow)
189
+
190
+ - **RISK_SOURCE**: Parcel读取的不可信数据
191
+ - **RISK_TYPE**: 边界条件缺失
192
+ - **RISK_PATH**: 不可信数据 -> 循环/递归条件 -> 无限循环/栈溢出
193
+ - **IMPACT_POINT**: 系统资源耗尽、拒绝服务
194
+
195
+ ## 影响分析(ImpactAnalysis)
196
+
197
+ - **Trigger**: 使用Parcel数据作为循环或递归条件
198
+ - **Propagation**: 恶意构造超大数值导致无限循环或深度递归
199
+ - **Consequence**: CPU资源耗尽、栈溢出、系统崩溃
200
+ - **Mitigation**: 添加数值上限检查,限制循环次数和递归深度
201
+
202
+ ## 误报排除
203
+
204
+ | 场景 | 识别特征 | 处理方式 |
205
+ |------|----------|----------|
206
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
207
+ | 已有上限检查 | 存在常量比较或条件判断 | 不报 |
208
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
209
+ | 测试代码 | 位于 test 目录 | 自动跳过 |
210
+ ## 测试用例
211
+
212
+ ### 触发用例(应该报)
213
+
214
+ ```cpp
215
+ // test_BoundaryCondition_001_trigger.cpp
216
+ void trigger_bad_1(Parcel& parcel)
217
+ {
218
+ int count = parcel.ReadInt32();
219
+ for (int i = 0; i < count; i++) { // 应该报:无上限保护
220
+ ProcessItem(parcel);
221
+ }
222
+ }
223
+
224
+ void trigger_bad_2(Parcel& parcel)
225
+ {
226
+ int32_t n = parcel.ReadInt32();
227
+ while (n > 0) { // 应该报:无上限保护
228
+ HandleItem(parcel);
229
+ n--;
230
+ }
231
+ }
232
+
233
+ void trigger_bad_3(Parcel& parcel)
234
+ {
235
+ uint32_t depth = parcel.ReadUint32();
236
+ RecurseProcess(parcel, depth); // 应该报:递归深度未限制
237
+ }
238
+ ```
239
+
240
+ ### 安全用例(不应该报)
241
+
242
+ ```cpp
243
+ // test_BoundaryCondition_001_safe.cpp
244
+ constexpr int MAX_COUNT = 1000;
245
+
246
+ void safe_good_1(Parcel& parcel)
247
+ {
248
+ int count = parcel.ReadInt32();
249
+ if (count < 0 || count > MAX_COUNT) { // 安全:有上限保护
250
+ LOGE("Invalid count");
251
+ return;
252
+ }
253
+ for (int i = 0; i < count; i++) {
254
+ ProcessItem(parcel);
255
+ }
256
+ }
257
+
258
+ void safe_good_2(Parcel& parcel)
259
+ {
260
+ int count = parcel.ReadInt32();
261
+ count = std::min(count, MAX_COUNT); // 安全:限制上限
262
+ for (int i = 0; i < count; i++) {
263
+ ProcessItem(parcel);
264
+ }
265
+ }
266
+
267
+ // NOPROTECT: 特殊场景需要处理大数量
268
+ void noprotect_case(Parcel& parcel)
269
+ {
270
+ int count = parcel.ReadInt32();
271
+ for (int i = 0; i < count; i++) {
272
+ ProcessItem(parcel);
273
+ }
274
+ }
275
+ ```
@@ -0,0 +1,273 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_002"
3
+ name: "Parcel数据不可直接作为数组下标"
4
+ category: "边界条件"
5
+ severity: "CRITICAL"
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:Parcel数据直接作为数组下标
22
+ constexpr int BUFFER_SIZE = 100;
23
+
24
+ void ProcessBuffer(Parcel& parcel)
25
+ {
26
+ int index = parcel.ReadInt32(); // 不可信数据
27
+ int buffer[BUFFER_SIZE];
28
+ int value = buffer[index]; // 危险:index可能越界
29
+ }
30
+
31
+ // 错误示例2:Parcel数据用于多维数组访问
32
+ void ProcessMatrix(Parcel& parcel)
33
+ {
34
+ int matrix[10][10];
35
+ int row = parcel.ReadInt32();
36
+ int col = parcel.ReadInt32();
37
+ int value = matrix[row][col]; // 危险:row/col可能越界
38
+ }
39
+
40
+ // 错误示例3:Parcel数据作为数组索引赋值
41
+ void SetArrayValue(Parcel& parcel)
42
+ {
43
+ int arr[50];
44
+ int idx = parcel.ReadInt32();
45
+ arr[idx] = 100; // 危险:越界写入
46
+ }
47
+
48
+ // 错误示例4:全局数组使用Parcel下标
49
+ int g_data[256];
50
+
51
+ void UpdateGlobalData(Parcel& parcel)
52
+ {
53
+ int pos = parcel.ReadInt32();
54
+ g_data[pos] = parcel.ReadInt32(); // 危险:越界访问全局数组
55
+ }
56
+
57
+ // 错误示例5:类成员数组使用Parcel下标
58
+ class DataHandler {
59
+ private:
60
+ int data_[128];
61
+ public:
62
+ void Handle(Parcel& parcel) {
63
+ int idx = parcel.ReadInt32();
64
+ data_[idx] = 0; // 危险:越界访问成员数组
65
+ }
66
+ };
67
+ ```
68
+
69
+ ### ✅ 修复方案
70
+
71
+ ```cpp
72
+ // 正确示例1:添加边界检查
73
+ constexpr int BUFFER_SIZE = 100;
74
+
75
+ void ProcessBuffer(Parcel& parcel)
76
+ {
77
+ int index = parcel.ReadInt32();
78
+ if (index < 0 || index >= BUFFER_SIZE) {
79
+ LOGE("Invalid index: %d, valid range [0, %d)", index, BUFFER_SIZE);
80
+ return;
81
+ }
82
+ int buffer[BUFFER_SIZE];
83
+ int value = buffer[index];
84
+ }
85
+
86
+ // 正确示例2:多维数组边界检查
87
+ void ProcessMatrix(Parcel& parcel)
88
+ {
89
+ constexpr int ROWS = 10;
90
+ constexpr int COLS = 10;
91
+ int matrix[ROWS][COLS];
92
+
93
+ int row = parcel.ReadInt32();
94
+ int col = parcel.ReadInt32();
95
+
96
+ if (row < 0 || row >= ROWS || col < 0 || col >= COLS) {
97
+ LOGE("Invalid matrix index: [%d][%d]", row, col);
98
+ return;
99
+ }
100
+ int value = matrix[row][col];
101
+ }
102
+
103
+ // 正确示例3:安全的数组赋值
104
+ constexpr int ARRAY_SIZE = 50;
105
+
106
+ void SetArrayValue(Parcel& parcel)
107
+ {
108
+ int arr[ARRAY_SIZE];
109
+ int idx = parcel.ReadInt32();
110
+ if (idx >= 0 && idx < ARRAY_SIZE) {
111
+ arr[idx] = 100;
112
+ } else {
113
+ LOGE("Array index out of bounds: %d", idx);
114
+ }
115
+ }
116
+
117
+ // 正确示例4:全局数组的边界检查
118
+ constexpr int GLOBAL_DATA_SIZE = 256;
119
+ int g_data[GLOBAL_DATA_SIZE];
120
+
121
+ void UpdateGlobalData(Parcel& parcel)
122
+ {
123
+ int pos = parcel.ReadInt32();
124
+ if (pos < 0 || pos >= GLOBAL_DATA_SIZE) {
125
+ LOGE("Invalid position: %d", pos);
126
+ return;
127
+ }
128
+ g_data[pos] = parcel.ReadInt32();
129
+ }
130
+
131
+ // 正确示例5:使用安全的访问函数
132
+ class DataHandler {
133
+ private:
134
+ static constexpr int DATA_SIZE = 128;
135
+ int data_[DATA_SIZE];
136
+
137
+ bool IsValidIndex(int idx) const {
138
+ return idx >= 0 && idx < DATA_SIZE;
139
+ }
140
+
141
+ public:
142
+ void Handle(Parcel& parcel) {
143
+ int idx = parcel.ReadInt32();
144
+ if (!IsValidIndex(idx)) {
145
+ LOGE("Invalid index: %d", idx);
146
+ return;
147
+ }
148
+ data_[idx] = 0;
149
+ }
150
+ };
151
+ ```
152
+
153
+ ## 检测范围
154
+
155
+ 检查以下模式:
156
+
157
+ 1. Parcel读取值直接用于数组下标访问:`array[parcel.ReadInt32()]`
158
+ 2. Parcel读取的变量用于数组下标:`int idx = parcel.ReadInt32(); array[idx]`
159
+ 3. 成员数组使用Parcel数据作为下标
160
+ 4. 多维数组使用Parcel数据作为索引
161
+
162
+ ## 检测要点
163
+
164
+ 1. 识别固定大小数组的定义
165
+ 2. 追踪Parcel读取变量到数组访问
166
+ 3. 检查是否进行了边界检查
167
+ 4. 识别`array[index]`和`array[index] = value`模式
168
+ 5. 排除NOPROTECT标记的代码
169
+
170
+ ## 风险流分析(RiskFlow)
171
+
172
+ - **RISK_SOURCE**: Parcel读取的不可信数据
173
+ - **RISK_TYPE**: 数组越界访问
174
+ - **RISK_PATH**: 不可信数据 -> 数组下标 -> 越界读写
175
+ - **IMPACT_POINT**: 内存破坏、程序崩溃
176
+
177
+ ## 影响分析(ImpactAnalysis)
178
+
179
+ - **Trigger**: Parcel数据直接作为数组下标
180
+ - **Propagation**: 恶意构造超大或负数索引导致越界访问
181
+ - **Consequence**: 内存读取越界、内存写入越界、任意代码执行
182
+ - **Mitigation**: 使用前检查索引是否在有效范围内
183
+
184
+ ## 误报排除
185
+
186
+ | 场景 | 识别特征 | 处理方式 |
187
+ |------|----------|----------|
188
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
189
+ | 已有边界检查 | 存在范围判断条件 | 不报 |
190
+ | 动态数组 | 使用std::vector等容器 | 容器自身有边界检查 |
191
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
192
+ | 测试代码 | 位于 test 目录 | 自动跳过 |
193
+ ## 测试用例
194
+
195
+ ### 触发用例(应该报)
196
+
197
+ ```cpp
198
+ // test_BoundaryCondition_002_trigger.cpp
199
+ void trigger_bad_1(Parcel& parcel)
200
+ {
201
+ int buffer[100];
202
+ int idx = parcel.ReadInt32();
203
+ int val = buffer[idx]; // 应该报:无边界检查
204
+ }
205
+
206
+ void trigger_bad_2(Parcel& parcel)
207
+ {
208
+ int arr[50];
209
+ int pos = parcel.ReadInt32();
210
+ arr[pos] = 100; // 应该报:无边界检查
211
+ }
212
+
213
+ void trigger_bad_3(Parcel& parcel)
214
+ {
215
+ int matrix[10][10];
216
+ int row = parcel.ReadInt32();
217
+ int col = parcel.ReadInt32();
218
+ int val = matrix[row][col]; // 应该报:无边界检查
219
+ }
220
+
221
+ class Handler {
222
+ int data_[128];
223
+ public:
224
+ void trigger_bad_4(Parcel& parcel) {
225
+ int idx = parcel.ReadInt32();
226
+ data_[idx] = 0; // 应该报:成员数组越界
227
+ }
228
+ };
229
+ ```
230
+
231
+ ### 安全用例(不应该报)
232
+
233
+ ```cpp
234
+ // test_BoundaryCondition_002_safe.cpp
235
+ void safe_good_1(Parcel& parcel)
236
+ {
237
+ int buffer[100];
238
+ int idx = parcel.ReadInt32();
239
+ if (idx >= 0 && idx < 100) { // 安全:有边界检查
240
+ int val = buffer[idx];
241
+ }
242
+ }
243
+
244
+ void safe_good_2(Parcel& parcel)
245
+ {
246
+ std::vector<int> vec(100);
247
+ int idx = parcel.ReadInt32();
248
+ // 安全:vector的at()会进行边界检查
249
+ if (idx >= 0 && static_cast<size_t>(idx) < vec.size()) {
250
+ int val = vec[idx];
251
+ }
252
+ }
253
+
254
+ void safe_good_3(Parcel& parcel)
255
+ {
256
+ constexpr int SIZE = 50;
257
+ int arr[SIZE];
258
+ int pos = parcel.ReadInt32();
259
+ if (pos < 0 || pos >= SIZE) { // 安全:边界检查
260
+ LOGE("Invalid pos");
261
+ return;
262
+ }
263
+ arr[pos] = 100;
264
+ }
265
+
266
+ // NOPROTECT: 测试代码
267
+ void noprotect_case(Parcel& parcel)
268
+ {
269
+ int arr[10];
270
+ int idx = parcel.ReadInt32();
271
+ arr[idx] = 100;
272
+ }
273
+ ```