@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.
- package/README.md +169 -0
- package/SKILL.md +518 -0
- package/bin/install.js +165 -0
- package/config/rules.yaml +445 -0
- package/config/whitelist.yaml +52 -0
- package/package.json +40 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_001.md +275 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_002.md +273 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_003.md +305 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_004.md +350 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_005.md +301 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_006.md +320 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_007.md +432 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_008.md +394 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_009.md +425 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_010.md +472 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_011.md +204 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_012.md +210 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_013.md +226 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_014.md +222 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_015.md +256 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_016.md +269 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_017.md +222 -0
- package/references/BoundaryCondition/StabilityCodeReview_BoundaryCondition_018.md +336 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_001.md +414 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_002.md +335 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_003.md +284 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_004.md +313 -0
- package/references/ConcurrencyStability/StabilityCodeReview_ConcurrencyStability_005.md +364 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_001.md +142 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_002.md +222 -0
- package/references/ExceptionHandling/StabilityCodeReview_ExceptionHandling_003.md +383 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_001.md +258 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_002.md +131 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_003.md +220 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_004.md +224 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_005.md +250 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_006.md +153 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_007.md +169 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_008.md +153 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_009.md +144 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_010.md +152 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_011.md +221 -0
- package/references/GraphicsStability/StabilityCodeReview_GraphicsStability_012.md +318 -0
- package/references/InitializationOrder/StabilityCodeReview_InitializationOrder_001.md +411 -0
- package/references/Lifecycle/StabilityCodeReview_Lifecycle_001.md +255 -0
- package/references/Lifecycle/StabilityCodeReview_Lifecycle_002.md +177 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_001.md +332 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_002.md +261 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_003.md +428 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_004.md +400 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_005.md +364 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_006.md +359 -0
- package/references/MemoryStability/StabilityCodeReview_MemoryStability_007.md +279 -0
- package/references/PROBLEM_TEMPLATE.md +65 -0
- package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_001.md +380 -0
- package/references/PerformanceStability/StabilityCodeReview_PerformanceStability_002.md +437 -0
- package/references/REPORT_TEMPLATE.csv +5 -0
- package/references/REPORT_TEMPLATE.md +132 -0
- package/references/RULE_DEVELOPMENT_GUIDE.md +711 -0
- package/references/RULE_INDEX.md +101 -0
- package/references/RULE_TEMPLATE.md +192 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_001.md +334 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_002.md +425 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_003.md +420 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_004.md +409 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_005.md +445 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_006.md +384 -0
- package/references/ResourceManagement/StabilityCodeReview_ResourceManagement_007.md +395 -0
- package/scripts/add-rule.py +423 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
---
|
|
2
|
+
rule_id: "StabilityCodeReview_ResourceManagement_006"
|
|
3
|
+
name: "JSON对象未关闭泄漏"
|
|
4
|
+
category: "资源管理"
|
|
5
|
+
severity: "MEDIUM"
|
|
6
|
+
language: ["cpp", "c", "c++"]
|
|
7
|
+
author: "OH-Department7 Stability Team"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# JSON对象未关闭泄漏
|
|
11
|
+
|
|
12
|
+
## 问题描述
|
|
13
|
+
|
|
14
|
+
使用json库(如cJSON、json-c等)相关操作完毕后应记得使用close/put释放内存。JSON对象在创建或解析时会分配内存,如果不及时释放,会导致内存泄漏。
|
|
15
|
+
|
|
16
|
+
## 检测示例
|
|
17
|
+
|
|
18
|
+
### ❌ 问题代码
|
|
19
|
+
|
|
20
|
+
```cpp
|
|
21
|
+
// 场景1:cJSON_Parse后异常分支未删除
|
|
22
|
+
cJSON* parse_config(const char* json_str) {
|
|
23
|
+
cJSON* root = cJSON_Parse(json_str); // 创建JSON对象
|
|
24
|
+
if (root == nullptr) {
|
|
25
|
+
return nullptr;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
cJSON* name = cJSON_GetObjectItem(root, "name");
|
|
29
|
+
if (name == nullptr) {
|
|
30
|
+
return nullptr; // 错误:root泄漏
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
cJSON* value = cJSON_GetObjectItem(root, "value");
|
|
34
|
+
if (value == nullptr) {
|
|
35
|
+
return nullptr; // 错误:root泄漏
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 处理数据...
|
|
39
|
+
return root;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 场景2:cJSON_CreateObject后泄漏
|
|
43
|
+
cJSON* create_response(int code, const char* msg) {
|
|
44
|
+
cJSON* root = cJSON_CreateObject(); // 创建JSON对象
|
|
45
|
+
if (root == nullptr) {
|
|
46
|
+
return nullptr;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
cJSON* data = cJSON_CreateObject();
|
|
50
|
+
if (data == nullptr) {
|
|
51
|
+
return nullptr; // 错误:root泄漏
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (cJSON_AddStringToObject(root, "message", msg) == nullptr) {
|
|
55
|
+
cJSON_Delete(data);
|
|
56
|
+
return nullptr; // 错误:root泄漏
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
cJSON_AddItemToObject(root, "data", data);
|
|
60
|
+
return root;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 场景3:json-c库泄漏
|
|
64
|
+
struct json_object* load_config(const char* path) {
|
|
65
|
+
struct json_object* root = json_object_from_file(path); // 加载JSON
|
|
66
|
+
if (root == nullptr) {
|
|
67
|
+
return nullptr;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
struct json_object* item = json_object_object_get(root, "config");
|
|
71
|
+
if (item == nullptr) {
|
|
72
|
+
return nullptr; // 错误:root泄漏
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 处理config...
|
|
76
|
+
return root;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 场景4:循环中创建JSON对象泄漏
|
|
80
|
+
int process_array(const char* json_str) {
|
|
81
|
+
cJSON* root = cJSON_Parse(json_str);
|
|
82
|
+
if (root == nullptr) {
|
|
83
|
+
return -1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
cJSON* arr = cJSON_GetObjectItem(root, "items");
|
|
87
|
+
if (arr == nullptr) {
|
|
88
|
+
cJSON_Delete(root);
|
|
89
|
+
return -1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
int count = 0;
|
|
93
|
+
cJSON* item = nullptr;
|
|
94
|
+
cJSON_ArrayForEach(item, arr) {
|
|
95
|
+
cJSON* copy = cJSON_Duplicate(item, 1); // 复制对象
|
|
96
|
+
if (copy == nullptr) {
|
|
97
|
+
continue; // 错误:如果循环中断,root可能泄漏
|
|
98
|
+
}
|
|
99
|
+
// 处理copy...
|
|
100
|
+
cJSON_Delete(copy);
|
|
101
|
+
count++;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
cJSON_Delete(root);
|
|
105
|
+
return count;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 场景5:解析嵌套对象泄漏
|
|
109
|
+
int parse_nested(const char* json_str) {
|
|
110
|
+
cJSON* root = cJSON_Parse(json_str);
|
|
111
|
+
if (root == nullptr) {
|
|
112
|
+
return -1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
cJSON* outer = cJSON_GetObjectItem(root, "outer");
|
|
116
|
+
if (outer == nullptr) {
|
|
117
|
+
return -1; // 错误:root泄漏
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
cJSON* inner = cJSON_GetObjectItem(outer, "inner");
|
|
121
|
+
if (inner == nullptr) {
|
|
122
|
+
return -1; // 错误:root泄漏
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
int value = cJSON_GetObjectItem(inner, "value")->valueint;
|
|
126
|
+
cJSON_Delete(root);
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### ✅ 修复方案
|
|
132
|
+
|
|
133
|
+
```cpp
|
|
134
|
+
// 修复场景1:异常分支释放
|
|
135
|
+
cJSON* parse_config(const char* json_str) {
|
|
136
|
+
cJSON* root = cJSON_Parse(json_str);
|
|
137
|
+
if (root == nullptr) {
|
|
138
|
+
return nullptr;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
cJSON* name = cJSON_GetObjectItem(root, "name");
|
|
142
|
+
if (name == nullptr) {
|
|
143
|
+
cJSON_Delete(root); // 正确:释放root
|
|
144
|
+
return nullptr;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
cJSON* value = cJSON_GetObjectItem(root, "value");
|
|
148
|
+
if (value == nullptr) {
|
|
149
|
+
cJSON_Delete(root); // 正确:释放root
|
|
150
|
+
return nullptr;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return root; // 调用者负责释放
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// 修复场景2:使用RAII封装
|
|
157
|
+
class CJsonGuard {
|
|
158
|
+
public:
|
|
159
|
+
explicit CJsonGuard(cJSON* obj) : obj_(obj) {}
|
|
160
|
+
~CJsonGuard() { if (obj_) cJSON_Delete(obj_); }
|
|
161
|
+
cJSON* get() const { return obj_; }
|
|
162
|
+
cJSON* release() { cJSON* tmp = obj_; obj_ = nullptr; return tmp; }
|
|
163
|
+
private:
|
|
164
|
+
cJSON* obj_;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
cJSON* create_response(int code, const char* msg) {
|
|
168
|
+
CJsonGuard root(cJSON_CreateObject());
|
|
169
|
+
if (root.get() == nullptr) {
|
|
170
|
+
return nullptr;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
CJsonGuard data(cJSON_CreateObject());
|
|
174
|
+
if (data.get() == nullptr) {
|
|
175
|
+
return nullptr; // root自动释放
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (cJSON_AddStringToObject(root.get(), "message", msg) == nullptr) {
|
|
179
|
+
return nullptr; // root和data自动释放
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
cJSON_AddItemToObject(root.get(), "data", data.release());
|
|
183
|
+
return root.release();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 修复场景3:json-c库使用json_object_put
|
|
187
|
+
int load_and_process(const char* path) {
|
|
188
|
+
struct json_object* root = json_object_from_file(path);
|
|
189
|
+
if (root == nullptr) {
|
|
190
|
+
return -1;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
struct json_object* item = json_object_object_get(root, "config");
|
|
194
|
+
if (item == nullptr) {
|
|
195
|
+
json_object_put(root); // 正确:释放root
|
|
196
|
+
return -1;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
int result = 0;
|
|
200
|
+
// 处理config...
|
|
201
|
+
|
|
202
|
+
json_object_put(root);
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// 修复场景4:循环中正确管理
|
|
207
|
+
int process_array_safe(const char* json_str) {
|
|
208
|
+
CJsonGuard root(cJSON_Parse(json_str));
|
|
209
|
+
if (root.get() == nullptr) {
|
|
210
|
+
return -1;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
cJSON* arr = cJSON_GetObjectItem(root.get(), "items");
|
|
214
|
+
if (arr == nullptr) {
|
|
215
|
+
return -1;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
int count = 0;
|
|
219
|
+
cJSON* item = nullptr;
|
|
220
|
+
cJSON_ArrayForEach(item, arr) {
|
|
221
|
+
CJsonGuard copy(cJSON_Duplicate(item, 1));
|
|
222
|
+
if (copy.get() == nullptr) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
// 处理copy...
|
|
226
|
+
count++;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return count;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 修复场景5:goto统一清理
|
|
233
|
+
int parse_nested_goto(const char* json_str) {
|
|
234
|
+
cJSON* root = nullptr;
|
|
235
|
+
int result = -1;
|
|
236
|
+
|
|
237
|
+
root = cJSON_Parse(json_str);
|
|
238
|
+
if (root == nullptr) {
|
|
239
|
+
goto error;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
cJSON* outer = cJSON_GetObjectItem(root, "outer");
|
|
243
|
+
if (outer == nullptr) {
|
|
244
|
+
goto error;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
cJSON* inner = cJSON_GetObjectItem(outer, "inner");
|
|
248
|
+
if (inner == nullptr) {
|
|
249
|
+
goto error;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
result = cJSON_GetObjectItem(inner, "value")->valueint;
|
|
253
|
+
|
|
254
|
+
error:
|
|
255
|
+
if (root) {
|
|
256
|
+
cJSON_Delete(root);
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## 检测范围
|
|
263
|
+
|
|
264
|
+
检查以下模式:
|
|
265
|
+
|
|
266
|
+
- `cJSON_Parse/cJSON_ParseWithOpts` 解析JSON
|
|
267
|
+
- `cJSON_CreateObject/cJSON_CreateArray` 创建JSON对象
|
|
268
|
+
- `cJSON_Duplicate` 复制JSON对象
|
|
269
|
+
- `json_object_new_object/json_object_new_array` (json-c库)
|
|
270
|
+
- `json_object_from_file/json_tokener_parse` (json-c库)
|
|
271
|
+
- 异常分支未调用`cJSON_Delete/json_object_put`
|
|
272
|
+
|
|
273
|
+
## 检测要点
|
|
274
|
+
|
|
275
|
+
1. 识别JSON对象创建操作
|
|
276
|
+
2. 追踪JSON变量到函数结束
|
|
277
|
+
3. 检查异常返回分支是否释放JSON对象
|
|
278
|
+
4. 排除使用RAII封装或返回JSON对象的情况
|
|
279
|
+
|
|
280
|
+
## 风险流分析(RiskFlow)
|
|
281
|
+
|
|
282
|
+
- **RISK_SOURCE**:创建/解析的JSON对象
|
|
283
|
+
- **RISK_TYPE**:内存泄漏
|
|
284
|
+
- **RISK_PATH**:JSON创建 -> 异常返回 -> 未close -> 内存泄漏
|
|
285
|
+
- **IMPACT_POINT**:内存资源耗尽、程序稳定性下降
|
|
286
|
+
|
|
287
|
+
## 影响分析(ImpactAnalysis)
|
|
288
|
+
|
|
289
|
+
- **Trigger**:异常分支返回时JSON对象未释放
|
|
290
|
+
- **Propagation**:内存泄漏累积,进程内存持续增长
|
|
291
|
+
- **Consequence**:内存耗尽、程序崩溃、服务不可用
|
|
292
|
+
- **Mitigation**:使用cJSON_Delete/json_object_put释放JSON对象,或使用RAII封装
|
|
293
|
+
|
|
294
|
+
## 误报排除
|
|
295
|
+
|
|
296
|
+
| 场景 | 识别特征 | 处理方式 |
|
|
297
|
+
|------|----------|----------|
|
|
298
|
+
| 返回JSON对象 | return json变量 | 不报 |
|
|
299
|
+
| 使用RAII封装 | CJsonGuard等 | 不报 |
|
|
300
|
+
| 有delete/put释放 | cJSON_Delete/json_object_put | 不报 |
|
|
301
|
+
| NOPROTECT标记 | 有 // NOPROTECT 注释 | 不报 |
|
|
302
|
+
| 第三方库 | 位于 third_party 目录 | 白名单排除 |
|
|
303
|
+
## 测试用例
|
|
304
|
+
|
|
305
|
+
### 触发用例(应该报)
|
|
306
|
+
|
|
307
|
+
```cpp
|
|
308
|
+
// test_ResourceManagement_006_trigger.cpp
|
|
309
|
+
cJSON* trigger_bad_1(const char* json_str) {
|
|
310
|
+
cJSON* root = cJSON_Parse(json_str); // 应该报:JSON泄漏
|
|
311
|
+
if (root == nullptr) {
|
|
312
|
+
return nullptr;
|
|
313
|
+
}
|
|
314
|
+
cJSON* item = cJSON_GetObjectItem(root, "key");
|
|
315
|
+
if (item == nullptr) {
|
|
316
|
+
return nullptr; // root泄漏
|
|
317
|
+
}
|
|
318
|
+
return root;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
cJSON* trigger_bad_2(int code) {
|
|
322
|
+
cJSON* root = cJSON_CreateObject(); // 应该报:JSON泄漏
|
|
323
|
+
if (root == nullptr) {
|
|
324
|
+
return nullptr;
|
|
325
|
+
}
|
|
326
|
+
cJSON* data = cJSON_CreateObject();
|
|
327
|
+
if (data == nullptr) {
|
|
328
|
+
return nullptr; // root泄漏
|
|
329
|
+
}
|
|
330
|
+
cJSON_AddItemToObject(root, "data", data);
|
|
331
|
+
return root;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
struct json_object* trigger_bad_3(const char* path) {
|
|
335
|
+
struct json_object* root = json_object_from_file(path); // 应该报:JSON泄漏
|
|
336
|
+
if (root == nullptr) {
|
|
337
|
+
return nullptr;
|
|
338
|
+
}
|
|
339
|
+
struct json_object* item = json_object_object_get(root, "config");
|
|
340
|
+
if (item == nullptr) {
|
|
341
|
+
return nullptr; // root泄漏
|
|
342
|
+
}
|
|
343
|
+
return root;
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### 安全用例(不应该报)
|
|
348
|
+
|
|
349
|
+
```cpp
|
|
350
|
+
// test_ResourceManagement_006_safe.cpp
|
|
351
|
+
cJSON* safe_good_1(const char* json_str) {
|
|
352
|
+
cJSON* root = cJSON_Parse(json_str);
|
|
353
|
+
if (root == nullptr) {
|
|
354
|
+
return nullptr;
|
|
355
|
+
}
|
|
356
|
+
cJSON* item = cJSON_GetObjectItem(root, "key");
|
|
357
|
+
if (item == nullptr) {
|
|
358
|
+
cJSON_Delete(root); // 安全:手动释放
|
|
359
|
+
return nullptr;
|
|
360
|
+
}
|
|
361
|
+
return root;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
cJSON* safe_good_2(const char* json_str) {
|
|
365
|
+
CJsonGuard root(cJSON_Parse(json_str)); // 安全:RAII管理
|
|
366
|
+
if (root.get() == nullptr) {
|
|
367
|
+
return nullptr;
|
|
368
|
+
}
|
|
369
|
+
cJSON* item = cJSON_GetObjectItem(root.get(), "key");
|
|
370
|
+
if (item == nullptr) {
|
|
371
|
+
return nullptr;
|
|
372
|
+
}
|
|
373
|
+
return root.release();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// NOPROTECT: 测试代码
|
|
377
|
+
cJSON* noprotect_case(const char* json_str) {
|
|
378
|
+
cJSON* root = cJSON_Parse(json_str);
|
|
379
|
+
if (cJSON_GetObjectItem(root, "key") == nullptr) {
|
|
380
|
+
return nullptr;
|
|
381
|
+
}
|
|
382
|
+
return root;
|
|
383
|
+
}
|
|
384
|
+
```
|