@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,210 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_012"
3
+ name: "使用json库获取键值内容前应先判断类型是否匹配、键值是否存在"
4
+ category: "边界条件"
5
+ severity: "MEDIUM"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # 使用json库获取键值内容前应先判断类型是否匹配、键值是否存在
11
+
12
+ ## 问题描述
13
+
14
+ 直接访问json对象的键值而不检查键是否存在或类型是否匹配,可能导致程序崩溃、异常抛出或数据错误。恶意构造的json数据可能包含错误的类型,导致服务不可用。
15
+
16
+ ## 检测示例
17
+
18
+ ### ❌ 问题代码
19
+
20
+ ```cpp
21
+ // 错误示例1:直接访问键值不检查存在性
22
+ void ParseConfig(const Json::Value& config)
23
+ {
24
+ std::string name = config["name"].asString(); // 危险:键可能不存在
25
+ int port = config["port"].asInt(); // 危险:同上
26
+ }
27
+
28
+ // 错误示例2:不检查类型直接转换
29
+ void ProcessJson(const Json::Value& data)
30
+ {
31
+ int count = data["count"].asInt(); // 危险:可能是其他类型
32
+ std::string value = data["value"].asString(); // 危险:同上
33
+ }
34
+
35
+ // 错误示例3:嵌套json访问
36
+ void ParseNested(const Json::Value& root)
37
+ {
38
+ int id = root["user"]["id"].asInt(); // 危险:user可能不存在
39
+ std::string name = root["user"]["profile"]["name"].asString(); // 危险:多层不检查
40
+ }
41
+
42
+ // 错误示例4:数组访问
43
+ void ProcessArray(const Json::Value& arr, int index)
44
+ {
45
+ std::string item = arr[index].asString(); // 危险:可能越界或类型不匹配
46
+ }
47
+ ```
48
+
49
+ ### ✅ 修复方案
50
+
51
+ ```cpp
52
+ // 正确示例1:先检查键是否存在
53
+ void ParseConfig(const Json::Value& config)
54
+ {
55
+ if (!config.isMember("name") || !config["name"].isString()) {
56
+ LOGE("Invalid or missing 'name' field");
57
+ return;
58
+ }
59
+ std::string name = config["name"].asString();
60
+
61
+ if (!config.isMember("port") || !config["port"].isInt()) {
62
+ LOGE("Invalid or missing 'port' field");
63
+ return;
64
+ }
65
+ int port = config["port"].asInt();
66
+ }
67
+
68
+ // 正确示例2:使用安全的get方法
69
+ void ProcessJson(const Json::Value& data)
70
+ {
71
+ int count = data.get("count", 0).asInt(); // 提供默认值
72
+ std::string value = data.get("value", "").asString();
73
+
74
+ // 或者先检查类型
75
+ if (data.isMember("count") && data["count"].isInt()) {
76
+ int count = data["count"].asInt();
77
+ }
78
+ }
79
+
80
+ // 正确示例3:嵌套json安全访问
81
+ void ParseNested(const Json::Value& root)
82
+ {
83
+ if (!root.isMember("user") || !root["user"].isObject()) {
84
+ LOGE("Missing or invalid 'user' object");
85
+ return;
86
+ }
87
+ const Json::Value& user = root["user"];
88
+
89
+ if (!user.isMember("id") || !user["id"].isInt()) {
90
+ LOGE("Missing or invalid 'user.id'");
91
+ return;
92
+ }
93
+ int id = user["id"].asInt();
94
+ }
95
+
96
+ // 正确示例4:数组安全访问
97
+ void ProcessArray(const Json::Value& arr, int index)
98
+ {
99
+ if (!arr.isArray() || index < 0 || index >= arr.size()) {
100
+ LOGE("Invalid array or index");
101
+ return;
102
+ }
103
+ if (!arr[index].isString()) {
104
+ LOGE("Array element is not string");
105
+ return;
106
+ }
107
+ std::string item = arr[index].asString();
108
+ }
109
+ ```
110
+
111
+ ## 检测范围
112
+
113
+ 检查以下模式:
114
+
115
+ - `json["key"]` 直接访问后调用 `.asXxx()`
116
+ - `json[key]` 变量作为键访问
117
+ - 嵌套访问 `json["a"]["b"]["c"]`
118
+ - 数组访问 `json[index]`
119
+ - 类型转换方法:`asString()`、`asInt()`、`asDouble()`、`asBool()`、`asArray()`、`asObject()`
120
+
121
+ ## 检测要点
122
+
123
+ 1. 识别json键值访问表达式
124
+ 2. 检查是否在访问前调用了 `isMember()`、`has()`、`contains()`
125
+ 3. 检查是否在转换前调用了类型检查方法:`isString()`、`isInt()` 等
126
+ 4. 检查是否使用了安全的 `get()` 方法
127
+ 5. 排除NOPROTECT标记的代码
128
+
129
+ ## 风险流分析(RiskFlow)
130
+
131
+ - **RISK_SOURCE**: json对象键值访问
132
+ - **RISK_TYPE**: 键不存在/类型不匹配
133
+ - **RISK_PATH**: 直接访问键值 -> 键不存在或类型错误 -> 异常/崩溃
134
+ - **IMPACT_POINT**: 服务异常、程序崩溃
135
+
136
+ ## 影响分析(ImpactAnalysis)
137
+
138
+ - **Trigger**: 访问不存在的键或类型不匹配的值
139
+ - **Propagation**: 抛出异常或返回错误默认值
140
+ - **Consequence**: 程序崩溃、服务不可用、数据错误
141
+ - **Mitigation**: 访问前检查键存在性和类型匹配性
142
+
143
+ ## 误报排除
144
+
145
+ | 场景 | 识别特征 | 处理方式 |
146
+ |------|----------|----------|
147
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
148
+ | 已有检查 | 存在 isMember、isXxx 调用 | 不报 |
149
+ | 使用get方法 | 使用 .get() 安全方法 | 不报 |
150
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
151
+ | 测试代码 | 位于 test 目录 | 自动跳过 |
152
+ ## 测试用例
153
+
154
+ ### 触发用例(应该报)
155
+
156
+ ```cpp
157
+ // test_BoundaryCondition_012_trigger.cpp
158
+ void trigger_bad_1(const Json::Value& config)
159
+ {
160
+ std::string name = config["name"].asString(); // 应该报:未检查键存在性和类型
161
+ }
162
+
163
+ void trigger_bad_2(const Json::Value& data)
164
+ {
165
+ int count = data["count"].asInt(); // 应该报:未检查类型
166
+ }
167
+
168
+ void trigger_bad_3(const Json::Value& root)
169
+ {
170
+ int id = root["user"]["id"].asInt(); // 应该报:嵌套访问未检查
171
+ }
172
+
173
+ void trigger_bad_4(const Json::Value& arr, int idx)
174
+ {
175
+ std::string item = arr[idx].asString(); // 应该报:数组访问未检查
176
+ }
177
+ ```
178
+
179
+ ### 安全用例(不应该报)
180
+
181
+ ```cpp
182
+ // test_BoundaryCondition_012_safe.cpp
183
+ void safe_good_1(const Json::Value& config)
184
+ {
185
+ if (config.isMember("name") && config["name"].isString()) { // 安全:有检查
186
+ std::string name = config["name"].asString();
187
+ }
188
+ }
189
+
190
+ void safe_good_2(const Json::Value& data)
191
+ {
192
+ int count = data.get("count", 0).asInt(); // 安全:使用默认值
193
+ }
194
+
195
+ void safe_good_3(const Json::Value& root)
196
+ {
197
+ if (root.isMember("user") && root["user"].isObject()) { // 安全:有检查
198
+ const Json::Value& user = root["user"];
199
+ if (user.isMember("id") && user["id"].isInt()) {
200
+ int id = user["id"].asInt();
201
+ }
202
+ }
203
+ }
204
+
205
+ // NOPROTECT: 已确认数据格式正确
206
+ void noprotect_case(const Json::Value& data)
207
+ {
208
+ std::string value = data["value"].asString(); // 已确认格式
209
+ }
210
+ ```
@@ -0,0 +1,226 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_013"
3
+ name: "使用json库获取键值后,在进行类型转换前应先校验参数类型"
4
+ category: "边界条件"
5
+ severity: "MEDIUM"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # 使用json库获取键值后,在进行类型转换前应先校验参数类型
11
+
12
+ ## 问题描述
13
+
14
+ 获取json值后直接进行类型转换,未校验实际类型是否与期望类型匹配,可能导致类型转换异常、数据错误或程序崩溃。恶意构造的json数据可能包含错误类型,造成服务异常。
15
+
16
+ ## 检测示例
17
+
18
+ ### ❌ 问题代码
19
+
20
+ ```cpp
21
+ // 错误示例1:获取值后直接转换类型
22
+ void ProcessValue(const Json::Value& data)
23
+ {
24
+ int count = data["count"].asInt(); // 危险:未检查是否为int类型
25
+ std::string name = data["name"].asString(); // 危险:未检查是否为string类型
26
+ }
27
+
28
+ // 错误示例2:假设类型进行转换
29
+ void ParseConfig(const Json::Value& config)
30
+ {
31
+ double value = config["value"].asDouble(); // 危险:可能是int或string
32
+ bool enabled = config["enabled"].asBool(); // 危险:可能是string "true"
33
+ }
34
+
35
+ // 错误示例3:强制类型转换
36
+ void HandleData(const Json::Value& json)
37
+ {
38
+ const Json::Value& arr = json["items"];
39
+ for (int i = 0; i < arr.size(); i++) {
40
+ std::string item = arr[i].asString(); // 危险:元素可能不是string
41
+ }
42
+ }
43
+
44
+ // 错误示例4:static_cast转换
45
+ void ConvertValue(const Json::Value& data)
46
+ {
47
+ int64_t id = static_cast<int64_t>(data["id"].asInt64()); // 危险:未检查类型
48
+ float rate = static_cast<float>(data["rate"].asDouble()); // 危险:未检查类型
49
+ }
50
+ ```
51
+
52
+ ### ✅ 修复方案
53
+
54
+ ```cpp
55
+ // 正确示例1:转换前检查类型
56
+ void ProcessValue(const Json::Value& data)
57
+ {
58
+ if (!data["count"].isInt()) {
59
+ LOGE("'count' is not an integer");
60
+ return;
61
+ }
62
+ int count = data["count"].asInt();
63
+
64
+ if (!data["name"].isString()) {
65
+ LOGE("'name' is not a string");
66
+ return;
67
+ }
68
+ std::string name = data["name"].asString();
69
+ }
70
+
71
+ // 正确示例2:使用isXxx系列方法
72
+ void ParseConfig(const Json::Value& config)
73
+ {
74
+ if (config["value"].isDouble()) {
75
+ double value = config["value"].asDouble();
76
+ } else if (config["value"].isInt()) {
77
+ double value = static_cast<double>(config["value"].asInt());
78
+ } else if (config["value"].isString()) {
79
+ // 处理字符串转换
80
+ } else {
81
+ LOGE("Invalid 'value' type");
82
+ }
83
+
84
+ if (config["enabled"].isBool()) {
85
+ bool enabled = config["enabled"].asBool();
86
+ } else if (config["enabled"].isString()) {
87
+ bool enabled = (config["enabled"].asString() == "true");
88
+ }
89
+ }
90
+
91
+ // 正确示例3:数组元素类型检查
92
+ void HandleData(const Json::Value& json)
93
+ {
94
+ const Json::Value& arr = json["items"];
95
+ if (!arr.isArray()) {
96
+ LOGE("'items' is not an array");
97
+ return;
98
+ }
99
+ for (int i = 0; i < arr.size(); i++) {
100
+ if (!arr[i].isString()) {
101
+ LOGE("Item %d is not string", i);
102
+ continue;
103
+ }
104
+ std::string item = arr[i].asString();
105
+ }
106
+ }
107
+
108
+ // 正确示例4:结合null检查
109
+ void ConvertValue(const Json::Value& data)
110
+ {
111
+ if (data["id"].isNull()) {
112
+ LOGE("'id' is null");
113
+ return;
114
+ }
115
+ if (!data["id"].isInt64() && !data["id"].isInt()) {
116
+ LOGE("'id' is not an integer type");
117
+ return;
118
+ }
119
+ int64_t id = data["id"].asInt64();
120
+ }
121
+ ```
122
+
123
+ ## 检测范围
124
+
125
+ 检查以下类型转换方法:
126
+
127
+ - `asString()` - 转换为字符串
128
+ - `asInt()`、`asInt64()` - 转换为整数
129
+ - `asUInt()`、`asUInt64()` - 转换为无符号整数
130
+ - `asDouble()`、`asFloat()` - 转换为浮点数
131
+ - `asBool()` - 转换为布尔值
132
+ - `asArray()` - 转换为数组
133
+ - `asObject()` - 转换为对象
134
+ - `static_cast<T>(value.asXxx())` - 强制类型转换
135
+
136
+ ## 检测要点
137
+
138
+ 1. 识别 `.asXxx()` 类型转换调用
139
+ 2. 检查是否在转换前调用了对应的 `isXxx()` 方法
140
+ 3. 检查是否使用了安全的默认值方法
141
+ 4. 检查 `static_cast` 前是否有类型校验
142
+ 5. 排除NOPROTECT标记的代码
143
+
144
+ ## 风险流分析(RiskFlow)
145
+
146
+ - **RISK_SOURCE**: json值类型转换
147
+ - **RISK_TYPE**: 类型转换异常
148
+ - **RISK_PATH**: 未校验类型 -> 强制转换 -> 数据错误或异常
149
+ - **IMPACT_POINT**: 数据损坏、程序崩溃
150
+
151
+ ## 影响分析(ImpactAnalysis)
152
+
153
+ - **Trigger**: 类型不匹配时进行强制转换
154
+ - **Propagation**: 数据被错误解释或抛出异常
155
+ - **Consequence**: 数据损坏、程序异常、服务不可用
156
+ - **Mitigation**: 转换前使用 `isXxx()` 方法校验类型
157
+
158
+ ## 误报排除
159
+
160
+ | 场景 | 识别特征 | 处理方式 |
161
+ |------|----------|----------|
162
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
163
+ | 已有类型检查 | 存在 isXxx() 调用 | 不报 |
164
+ | 使用get默认值 | 使用 .get() 安全方法 | 不报 |
165
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
166
+ | 测试代码 | 位于 test 目录 | 自动跳过 |
167
+ ## 测试用例
168
+
169
+ ### 触发用例(应该报)
170
+
171
+ ```cpp
172
+ // test_BoundaryCondition_013_trigger.cpp
173
+ void trigger_bad_1(const Json::Value& data)
174
+ {
175
+ int count = data["count"].asInt(); // 应该报:未检查类型
176
+ }
177
+
178
+ void trigger_bad_2(const Json::Value& config)
179
+ {
180
+ std::string name = config["name"].asString(); // 应该报:未检查类型
181
+ }
182
+
183
+ void trigger_bad_3(const Json::Value& json)
184
+ {
185
+ double value = json["value"].asDouble(); // 应该报:未检查类型
186
+ }
187
+
188
+ void trigger_bad_4(const Json::Value& arr)
189
+ {
190
+ for (int i = 0; i < arr.size(); i++) {
191
+ std::string item = arr[i].asString(); // 应该报:未检查元素类型
192
+ }
193
+ }
194
+ ```
195
+
196
+ ### 安全用例(不应该报)
197
+
198
+ ```cpp
199
+ // test_BoundaryCondition_013_safe.cpp
200
+ void safe_good_1(const Json::Value& data)
201
+ {
202
+ if (data["count"].isInt()) { // 安全:有类型检查
203
+ int count = data["count"].asInt();
204
+ }
205
+ }
206
+
207
+ void safe_good_2(const Json::Value& config)
208
+ {
209
+ if (config.isMember("name") && config["name"].isString()) { // 安全:有检查
210
+ std::string name = config["name"].asString();
211
+ }
212
+ }
213
+
214
+ void safe_good_3(const Json::Value& json)
215
+ {
216
+ if (json["value"].isDouble() || json["value"].isInt()) { // 安全:有类型检查
217
+ double value = json["value"].asDouble();
218
+ }
219
+ }
220
+
221
+ // NOPROTECT: 已确认数据格式
222
+ void noprotect_case(const Json::Value& data)
223
+ {
224
+ int id = data["id"].asInt(); // 已确认类型正确
225
+ }
226
+ ```
@@ -0,0 +1,222 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_BoundaryCondition_014"
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 ProcessValue(int64_t bigValue)
23
+ {
24
+ int smallValue = (int)bigValue; // 危险:可能截断
25
+ array[smallValue] = data; // 可能导致越界
26
+ }
27
+
28
+ // 错误示例2:size_t转int
29
+ void AccessBuffer(size_t index, int offset)
30
+ {
31
+ int idx = (int)index + offset; // 危险:size_t可能超过INT_MAX
32
+ buffer[idx] = value;
33
+ }
34
+
35
+ // 错误示例3:无符号转有符号
36
+ void ProcessIndex(uint32_t unsignedIndex)
37
+ {
38
+ int signedIndex = (int)unsignedIndex; // 危险:若unsignedIndex > INT_MAX,变为负数
39
+ array[signedIndex] = data; // 可能越界访问
40
+ }
41
+
42
+ // 错误示例4:指针强制转换
43
+ void HandlePointer(void* ptr)
44
+ {
45
+ int* intPtr = (int*)ptr; // 危险:未检查对齐和有效性
46
+ *intPtr = 0; // 可能崩溃
47
+ }
48
+
49
+ // 错误示例5:double转int
50
+ void ConvertCoordinate(double coord)
51
+ {
52
+ int pixel = (int)coord; // 危险:double可能超出int范围
53
+ screen[pixel] = color;
54
+ }
55
+ ```
56
+
57
+ ### ✅ 修复方案
58
+
59
+ ```cpp
60
+ // 正确示例1:添加范围检查
61
+ void ProcessValue(int64_t bigValue)
62
+ {
63
+ if (bigValue > INT_MAX || bigValue < INT_MIN) {
64
+ LOGE("Value out of int range: %lld", bigValue);
65
+ return;
66
+ }
67
+ int smallValue = static_cast<int>(bigValue);
68
+ array[smallValue] = data;
69
+ }
70
+
71
+ // 正确示例2:使用saturated_cast
72
+ void AccessBuffer(size_t index, int offset)
73
+ {
74
+ int idx = base::saturated_cast<int>(index) + offset;
75
+ if (idx < 0 || idx >= buffer_size) {
76
+ LOGE("Index out of range: %d", idx);
77
+ return;
78
+ }
79
+ buffer[idx] = value;
80
+ }
81
+
82
+ // 正确示例3:显式范围检查
83
+ void ProcessIndex(uint32_t unsignedIndex)
84
+ {
85
+ if (unsignedIndex > static_cast<uint32_t>(INT_MAX)) {
86
+ LOGE("Index exceeds INT_MAX: %u", unsignedIndex);
87
+ return;
88
+ }
89
+ int signedIndex = static_cast<int>(unsignedIndex);
90
+ array[signedIndex] = data;
91
+ }
92
+
93
+ // 正确示例4:安全的指针转换
94
+ void HandlePointer(void* ptr)
95
+ {
96
+ if (ptr == nullptr) {
97
+ LOGE("Null pointer");
98
+ return;
99
+ }
100
+ // 检查对齐
101
+ if (reinterpret_cast<uintptr_t>(ptr) % alignof(int) != 0) {
102
+ LOGE("Pointer not aligned for int");
103
+ return;
104
+ }
105
+ int* intPtr = static_cast<int*>(ptr);
106
+ *intPtr = 0;
107
+ }
108
+
109
+ // 正确示例5:浮点数范围检查
110
+ void ConvertCoordinate(double coord)
111
+ {
112
+ if (coord > INT_MAX || coord < INT_MIN || !std::isfinite(coord)) {
113
+ LOGE("Invalid coordinate: %f", coord);
114
+ return;
115
+ }
116
+ int pixel = static_cast<int>(coord);
117
+ if (pixel >= 0 && pixel < screen_size) {
118
+ screen[pixel] = color;
119
+ }
120
+ }
121
+ ```
122
+
123
+ ## 检测范围
124
+
125
+ 检查以下类型转换:
126
+
127
+ - `static_cast<小类型>(大类型值)`
128
+ - C风格转换 `(int)`、`(short)`、`(char)` 等
129
+ - `reinterpret_cast` 指针转换
130
+ - `size_t` → `int`
131
+ - `int64_t` → `int32_t`
132
+ - `uint32_t` → `int32_t`
133
+ - `double` → `int`
134
+
135
+ ## 检测要点
136
+
137
+ 1. 识别类型转换表达式
138
+ 2. 判断是否为大类型转小类型
139
+ 3. 检查是否有范围校验
140
+ 4. 检查是否使用了安全转换函数
141
+ 5. 排除NOPROTECT标记的代码
142
+
143
+ ## 风险流分析(RiskFlow)
144
+
145
+ - **RISK_SOURCE**: 类型强制转换
146
+ - **RISK_TYPE**: 数值截断/越界
147
+ - **RISK_PATH**: 大类型转小类型 -> 数值截断 -> 数据错误/越界访问
148
+ - **IMPACT_POINT**: 数据损坏、内存越界、安全漏洞
149
+
150
+ ## 影响分析(ImpactAnalysis)
151
+
152
+ - **Trigger**: 源值超出目标类型表示范围
153
+ - **Propagation**: 数值被截断或解释为负值
154
+ - **Consequence**: 数组越界、数据损坏、安全漏洞
155
+ - **Mitigation**: 转换前校验数值范围
156
+
157
+ ## 误报排除
158
+
159
+ | 场景 | 识别特征 | 处理方式 |
160
+ |------|----------|----------|
161
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
162
+ | 已有范围检查 | 存在 INT_MAX、范围比较 | 不报 |
163
+ | 使用安全转换 | 使用 saturated_cast、checked_cast | 不报 |
164
+ | 第三方库 | 位于 third_party 目录 | 白名单排除 |
165
+ | 测试代码 | 位于 test 目录 | 自动跳过 |
166
+ ## 测试用例
167
+
168
+ ### 触发用例(应该报)
169
+
170
+ ```cpp
171
+ // test_BoundaryCondition_014_trigger.cpp
172
+ void trigger_bad_1(int64_t bigValue)
173
+ {
174
+ int smallValue = (int)bigValue; // 应该报:未检查范围
175
+ }
176
+
177
+ void trigger_bad_2(size_t index)
178
+ {
179
+ int idx = static_cast<int>(index); // 应该报:未检查范围
180
+ }
181
+
182
+ void trigger_bad_3(uint32_t unsignedIndex)
183
+ {
184
+ int signedIndex = (int)unsignedIndex; // 应该报:可能变为负数
185
+ array[signedIndex] = data;
186
+ }
187
+
188
+ void trigger_bad_4(double coord)
189
+ {
190
+ int pixel = (int)coord; // 应该报:未检查范围
191
+ }
192
+ ```
193
+
194
+ ### 安全用例(不应该报)
195
+
196
+ ```cpp
197
+ // test_BoundaryCondition_014_safe.cpp
198
+ void safe_good_1(int64_t bigValue)
199
+ {
200
+ if (bigValue >= INT_MIN && bigValue <= INT_MAX) { // 安全:有范围检查
201
+ int smallValue = static_cast<int>(bigValue);
202
+ }
203
+ }
204
+
205
+ void safe_good_2(size_t index)
206
+ {
207
+ int idx = base::saturated_cast<int>(index); // 安全:使用saturated_cast
208
+ }
209
+
210
+ void safe_good_3(uint32_t unsignedIndex)
211
+ {
212
+ if (unsignedIndex <= static_cast<uint32_t>(INT_MAX)) { // 安全:有范围检查
213
+ int signedIndex = static_cast<int>(unsignedIndex);
214
+ }
215
+ }
216
+
217
+ // NOPROTECT: 已确认值在范围内
218
+ void noprotect_case(int64_t value)
219
+ {
220
+ int v = (int)value; // 已确认范围
221
+ }
222
+ ```