@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,153 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_GraphicsStability_008"
3
+ name: "GetBackendTexture线程限制"
4
+ category: "图形稳定性"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # GetBackendTexture线程限制
11
+
12
+ ## 问题描述
13
+
14
+ Surface/Image只能在其创建的线程中使用GetBackendTexture。在非创建线程调用GetBackendTexture会导致GPU资源状态不一致,引发纹理损坏或崩溃。
15
+
16
+ ## 检测示例
17
+
18
+ ### 错误示例
19
+
20
+ ```cpp
21
+ // 错误示例1:IO线程创建Surface,渲染线程GetBackendTexture
22
+ class TextureLoader {
23
+ public:
24
+ void LoadOnIOThread() {
25
+ // IO线程创建Surface
26
+ surface_ = Surface::MakeRenderTarget(contextIO, info); // IO线程创建
27
+ }
28
+
29
+ void GetTextureOnRenderThread() {
30
+ // 错误:渲染线程调用GetBackendTexture
31
+ BackendTexture backend = surface_->GetBackendTexture(); // 错误:跨线程
32
+ }
33
+
34
+ private:
35
+ sk_sp<Surface> surface_;
36
+ };
37
+
38
+ // 错误示例2:主线程创建Image,其他线程GetBackendTexture
39
+ void MainThread_CreateImage()
40
+ {
41
+ g_image = Image::MakeFromEncoded(encodedData); // 主线程创建
42
+ }
43
+
44
+ void WorkerThread_GetBackendTexture()
45
+ {
46
+ // 错误:Worker线程调用GetBackendTexture
47
+ BackendTexture backend = g_image->GetBackendTexture(); // 错误:跨线程
48
+ }
49
+
50
+ // 错误示例3:异步回调中使用GetBackendTexture
51
+ void OnSurfaceReady(Surface* surface)
52
+ {
53
+ // 在回调线程(非创建线程)中调用
54
+ BackendTexture backend = surface->GetBackendTexture(); // 错误
55
+ }
56
+ ```
57
+
58
+ ### 正确示例
59
+
60
+ ```cpp
61
+ // 正确示例1:创建线程调用GetBackendTexture
62
+ void RenderThread_Lifecycle()
63
+ {
64
+ // 正确:渲染线程创建
65
+ auto surface = Surface::MakeRenderTarget(context, info);
66
+
67
+ // 正确:渲染线程调用GetBackendTexture
68
+ BackendTexture backend = surface->GetBackendTexture(); // 正确:同线程
69
+
70
+ // 使用backend创建新资源
71
+ auto newSurface = Surface::MakeFromBackendTexture(context, backend, ...);
72
+ }
73
+
74
+ // 正确示例2:在创建Surface的线程传递BackendTexture
75
+ class SafeTextureManager {
76
+ public:
77
+ void CreateAndExport() {
78
+ // 主线程创建
79
+ surface_ = Surface::MakeRenderTarget(context_, info_);
80
+
81
+ // 正确:主线程获取BackendTexture
82
+ BackendTexture backend = surface_->GetBackendTexture(); // 正确
83
+
84
+ // 正确:传递BackendTexture给其他线程使用
85
+ SendBackendTextureToRenderThread(backend);
86
+ }
87
+
88
+ private:
89
+ sk_sp<Surface> surface_;
90
+ };
91
+
92
+ // 正确示例3:每个线程独立创建和访问
93
+ void ThreadA_OwnedSurface()
94
+ {
95
+ auto surface = Surface::MakeRenderTarget(contextA, info);
96
+ BackendTexture backend = surface->GetBackendTexture(); // 正确:同线程
97
+ }
98
+
99
+ void ThreadB_OwnedSurface()
100
+ {
101
+ auto surface = Surface::MakeRenderTarget(contextB, info);
102
+ BackendTexture backend = surface->GetBackendTexture(); // 正确:同线程
103
+ }
104
+ ```
105
+
106
+ ## 风险流分析(RiskFlow)
107
+
108
+ - **RISK_SOURCE**: GetBackendTexture跨线程调用
109
+ - **RISK_TYPE**: 线程安全违规
110
+ - **RISK_PATH**: 在非创建线程调用GetBackendTexture -> GPU资源状态不一致 -> 纹理损坏
111
+ - **IMPACT_POINT**: GPU崩溃、纹理损坏、渲染异常
112
+
113
+ ## 影响分析(ImpactAnalysis)
114
+
115
+ - **Trigger**: 非创建线程调用GetBackendTexture
116
+ - **Propagation**: GPU资源状态不一致
117
+ - **Consequence**: GPU崩溃、纹理损坏、渲染异常
118
+ - **Mitigation**: GetBackendTexture只能在创建Surface/Image的线程调用
119
+
120
+ ## 误报排除
121
+
122
+ | 场景 | 识别特征 | 处理方式 |
123
+ |------|----------|----------|
124
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
125
+ | 同线程创建访问 | 上下文分析确认同线程 | 不报 |
126
+ | 传递BackendTexture | 通过参数传递BackendTexture | 不报 |
127
+ ## 测试用例
128
+
129
+ ### 触发用例(应该报)
130
+
131
+ ```cpp
132
+ // IOThread创建,RenderThread调用GetBackendTexture
133
+ void IOThread_Create()
134
+ {
135
+ g_surface = Surface::MakeRenderTarget(...);
136
+ }
137
+
138
+ void RenderThread_GetBackend()
139
+ {
140
+ BackendTexture backend = g_surface->GetBackendTexture(); // 应该报:跨线程
141
+ }
142
+ ```
143
+
144
+ ### 安全用例(不应该报)
145
+
146
+ ```cpp
147
+ // 同一线程创建和GetBackendTexture
148
+ void RenderThread_CreateAndGet()
149
+ {
150
+ sk_sp<Surface> surface = Surface::MakeRenderTarget(...); // 渲染线程创建
151
+ BackendTexture backend = surface->GetBackendTexture(); // 不报:同线程
152
+ }
153
+ ```
@@ -0,0 +1,144 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_GraphicsStability_009"
3
+ name: "RSRenderNodeMap线程访问限制"
4
+ category: "图形稳定性"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # RSRenderNodeMap线程访问限制
11
+
12
+ ## 问题描述
13
+
14
+ RSRenderNodeMap只能在RSMainThread类(主线程)访问,不允许在其它线程访问。**RSMainThread类负责渲染的Prepare阶段**,需要访问RenderNodeMap进行节点遍历、遮挡计算等操作。RenderNodeMap存储渲染节点映射关系,是RSMainThread类的核心数据结构。RSUniRenderThread类(Process阶段)或其他线程访问会导致数据竞争和状态不一致。
15
+
16
+ **渲染流程说明**:
17
+ - RSMainThread类:负责Prepare及以前阶段,可以访问RenderNodeMap进行节点管理
18
+ - RSUniRenderThread类:负责Process及以后阶段,不应直接访问RenderNodeMap,应使用副本数据
19
+
20
+ ## 检测示例
21
+
22
+ ### 错误示例
23
+
24
+ ```cpp
25
+ // 错误示例1:RSUniRenderThread类访问RenderNodeMap
26
+ void RSUniRenderThread::ProcessRender()
27
+ {
28
+ // 错误:RSUniRenderThread类访问RenderNodeMap
29
+ auto nodeMap = GetRenderNodeMap(); // 错误:非RSMainThread类访问
30
+ auto node = nodeMap->GetNode(surfaceId); // 错误
31
+ }
32
+
33
+ // 错误示例2:IO线程访问RenderNodeMap
34
+ void IOThread::OnDataReceived()
35
+ {
36
+ // 错误:IO线程访问RenderNodeMap
37
+ auto node = renderNodeMap_->FindNodeById(nodeId); // 错误
38
+ node->UpdateFromData(data); // 错误
39
+ }
40
+
41
+ // 错误示例3:Worker线程操作RenderNodeMap
42
+ class RenderWorker {
43
+ public:
44
+ void DoWork() {
45
+ // 错误:Worker线程修改RenderNodeMap
46
+ g_renderNodeMap->RegisterNode(newNode); // 错误
47
+ }
48
+ };
49
+
50
+ // 错误示例4:回调中访问RenderNodeMap
51
+ void OnSurfaceCreatedCallback(SurfaceId id)
52
+ {
53
+ // 错误:回调可能在非主线程执行
54
+ auto node = renderNodeMap_->GetNode(id); // 错误
55
+ }
56
+ ```
57
+
58
+ ### 正确示例
59
+
60
+ ```cpp
61
+ // 正确示例1:RS主线程访问RenderNodeMap
62
+ void RSMainThread::HandleSurfaceCreated(SurfaceId id)
63
+ {
64
+ // 正确:主线程访问RenderNodeMap
65
+ auto nodeMap = GetRenderNodeMap(); // 正确
66
+ auto node = nodeMap->GetNode(id); // 正确
67
+ node->Initialize();
68
+ }
69
+
70
+ // 正确示例2:通过命令传递到主线程
71
+ void IOThread::OnDataReceived(NodeId id, const Data& data)
72
+ {
73
+ // 正确:通过命令传递
74
+ UpdateNodeCommand cmd;
75
+ cmd.nodeId = id;
76
+ cmd.data = data;
77
+
78
+ SubmitToMainThread(cmd); // 正确:发送到主线程处理
79
+ }
80
+
81
+ // 正确示例3:主线程处理回调
82
+ void RSMainThread::OnCallbackReceived(const Callback& cb)
83
+ {
84
+ // 正确:主线程处理回调中的RenderNodeMap操作
85
+ if (cb.type == UPDATE_NODE) {
86
+ auto node = renderNodeMap_->GetNode(cb.nodeId); // 正确
87
+ node->UpdateFromCallback(cb);
88
+ }
89
+ }
90
+
91
+ // 正确示例4:RSUniRenderThread类使用副本数据
92
+ void RSUniRenderThread::RenderFrame()
93
+ {
94
+ // 正确:使用RSMainThread类传递的副本数据
95
+ auto renderList = GetRenderListCopy(); // 正确:不直接访问Map
96
+
97
+ for (auto& item : renderList) {
98
+ RenderItem(item);
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## 风险流分析(RiskFlow)
104
+
105
+ - **RISK_SOURCE**: 非RSMainThread类(RS主线程)访问RSRenderNodeMap
106
+ - **RISK_TYPE**: 线程安全违规
107
+ - **RISK_PATH**: 非RSMainThread类访问RSRenderNodeMap -> 数据竞争 -> 渲染状态不一致
108
+ - **IMPACT_POINT**: 渲染异常、崩溃
109
+
110
+ ## 影响分析(ImpactAnalysis)
111
+
112
+ - **Trigger**: 非RSMainThread类访问RSRenderNodeMap
113
+ - **Propagation**: 数据竞争、状态不一致
114
+ - **Consequence**: 渲染异常、界面错乱、崩溃
115
+ - **Mitigation**: RSRenderNodeMap只能在RSMainThread类访问
116
+
117
+ ## 误报排除
118
+
119
+ | 场景 | 识别特征 | 处理方式 |
120
+ |------|----------|----------|
121
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
122
+ | 主线程上下文 | RSMainThread:: | 不报 |
123
+ | 使用副本数据 | GetRenderListCopy() | 不报 |
124
+ ## 测试用例
125
+
126
+ ### 触发用例(应该报)
127
+
128
+ ```cpp
129
+ // RSUniRenderThread类访问RenderNodeMap
130
+ void RSUniRenderThread::OnRender()
131
+ {
132
+ auto node = renderNodeMap->GetNode(id); // 应该报:非RSMainThread类访问
133
+ }
134
+ ```
135
+
136
+ ### 安全用例(不应该报)
137
+
138
+ ```cpp
139
+ // RSMainThread类访问RenderNodeMap
140
+ void RSMainThread::HandleNode()
141
+ {
142
+ auto node = renderNodeMap->GetNode(id); // 不报:RSMainThread类访问
143
+ }
144
+ ```
@@ -0,0 +1,152 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_GraphicsStability_010"
3
+ name: "回调函数执行进程限制"
4
+ category: "图形稳定性"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # 回调函数执行进程限制
11
+
12
+ ## 问题描述
13
+
14
+ 应用进程传入的回调函数不能在RS进程中执行,只能在应用进程执行。RS进程和应用进程有独立的地址空间和执行上下文,直接在RS进程执行应用回调会导致回调在错误的上下文中执行,引发崩溃或状态不一致。
15
+
16
+ ## 检测示例
17
+
18
+ ### 错误示例
19
+
20
+ ```cpp
21
+ // 错误示例1:RS进程直接执行应用回调
22
+ void RSProcess::OnRenderComplete(SurfaceId id)
23
+ {
24
+ auto callback = GetAppCallback(id);
25
+
26
+ // 错误:RS进程直接执行应用回调
27
+ callback->OnComplete(); // 错误:回调在错误进程执行
28
+ }
29
+
30
+ // 错误示例2:RS服务直接调用应用监听器
31
+ class RenderService {
32
+ public:
33
+ void NotifyAppListener(RenderResult result)
34
+ {
35
+ auto listener = appListener_; // 应用传入的监听器
36
+
37
+ // 错误:RS服务直接调用应用监听器
38
+ listener->OnResult(result); // 错误:跨进程调用
39
+ }
40
+ };
41
+
42
+ // 错误示例3:RS线程执行应用回调函数
43
+ void RSRenderThread::HandleCallback()
44
+ {
45
+ std::function<void()> appCallback = GetPendingCallback();
46
+
47
+ // 错误:RS线程执行应用回调
48
+ appCallback(); // 错误:回调在RS进程执行
49
+ }
50
+
51
+ // 错误示例4:RS进程的回调处理
52
+ void RenderServiceProcess::ProcessCallbacks()
53
+ {
54
+ for (auto& cb : pendingCallbacks_) {
55
+ // 错误:在RS进程执行应用回调
56
+ cb.execute(); // 错误
57
+ }
58
+ }
59
+ ```
60
+
61
+ ### 正确示例
62
+
63
+ ```cpp
64
+ // 正确示例1:通过IPC发送回调到应用进程
65
+ void RSProcess::OnRenderComplete(SurfaceId id)
66
+ {
67
+ auto callback = GetAppCallback(id);
68
+
69
+ // 正确:通过IPC发送到应用进程执行
70
+ PostCallbackToApp(callback); // 正确:IPC通知应用
71
+ }
72
+
73
+ // 正确示例2:使用消息机制通知应用
74
+ class RenderService {
75
+ public:
76
+ void NotifyAppListener(RenderResult result)
77
+ {
78
+ // 正确:通过IPC消息发送结果
79
+ SendResultToApp(result); // 正确
80
+
81
+ // 应用进程收到消息后执行回调
82
+ }
83
+ };
84
+
85
+ // 正确示例3:应用进程处理回调
86
+ void AppProcess::HandleRSMessage(const RSMessage& msg)
87
+ {
88
+ if (msg.type == RENDER_COMPLETE) {
89
+ // 正确:应用进程执行回调
90
+ auto callback = GetCallback(msg.surfaceId);
91
+ callback->OnComplete(); // 正确:在应用进程执行
92
+ }
93
+ }
94
+
95
+ // 正确示例4:使用Binder IPC传递
96
+ void RSProcess::ScheduleAppCallback(std::function<void()> callback)
97
+ {
98
+ // 正确:通过Binder IPC发送
99
+ BinderCallbackToken token = RegisterCallback(callback);
100
+ SendCallbackTokenToApp(token); // 正确
101
+
102
+ // 应用进程根据token执行回调
103
+ }
104
+ ```
105
+
106
+ ## 风险流分析(RiskFlow)
107
+
108
+ - **RISK_SOURCE**: RS进程直接执行应用回调函数
109
+ - **RISK_TYPE**: 进程边界违规
110
+ - **RISK_PATH**: RS进程执行应用回调 -> 回调在错误进程上下文执行 -> 状态不一致
111
+ - **IMPACT_POINT**: 回调失败、进程崩溃
112
+
113
+ ## 影响分析(ImpactAnalysis)
114
+
115
+ - **Trigger**: RS进程直接调用应用传入的回调
116
+ - **Propagation**: 回调在错误进程上下文执行
117
+ - **Consequence**: 回调失败、进程通信异常、崩溃
118
+ - **Mitigation**: 通过IPC将回调发送到应用进程执行
119
+
120
+ ## 误报排除
121
+
122
+ | 场景 | 识别特征 | 处理方式 |
123
+ |------|----------|----------|
124
+ | NOPROTECT 标记 | 有 // NOPROTECT 注释 | 不报 |
125
+ | IPC发送 | PostToApp、SendToApp | 不报 |
126
+ | 应用进程上下文 | AppProcess:: | 不报 |
127
+ ## 测试用例
128
+
129
+ ### 触发用例(应该报)
130
+
131
+ ```cpp
132
+ // RSProcess中直接执行应用回调
133
+ void RSProcess::OnComplete()
134
+ {
135
+ appCallback->OnComplete(); // 应该报:在RS进程执行应用回调
136
+ }
137
+ ```
138
+
139
+ ### 安全用例(不应该报)
140
+
141
+ ```cpp
142
+ // RSProcess通过IPC发送回调
143
+ void RSProcess::OnComplete()
144
+ {
145
+ PostCallbackToApp(appCallback); // 不报:通过IPC发送
146
+
147
+ // 应用进程执行回调
148
+ void AppProcess::HandleCallback()
149
+ {
150
+ appCallback->OnComplete(); // 不报:在应用进程执行
151
+ }
152
+ ```
@@ -0,0 +1,221 @@
1
+ ---
2
+ rule_id: "StabilityCodeReview_GraphicsStability_011"
3
+ name: "Vulkan信号量导出fd生命周期管理"
4
+ category: "图形稳定性"
5
+ severity: "HIGH"
6
+ language: ["cpp", "c++"]
7
+ author: "OH-Department7 Stability Team"
8
+ ---
9
+
10
+ # Vulkan信号量导出fd生命周期管理
11
+
12
+ ## 问题描述
13
+
14
+ 使用GetFenceFdFromSemaphore、vkGetSemaphoreFdKHR等接口从vulkan信号量中导出fd后,fd由调用方负责关闭。**最佳实践是**在判断fd合法后,**立刻**(无任何中间代码)用sptr<SyncFence>智能指针包裹,由该智能指针接管fd生命周期,在智能指针释放时会自动关闭fd。**注意:强调"立刻"二字,意味着在fd导出后、判断合法后,必须立即创建智能指针,中间不能有任何其他代码语句,以确保fd在任何代码路径下都不会泄漏。**若实在无法使用SyncFence类型,须非常谨慎处理每一处函数/作用域出口,确保手动释放fd,避免fd泄漏。
15
+
16
+ ## 检测示例
17
+
18
+ ### 错误示例
19
+
20
+ ```cpp
21
+ // 错误示例1:导出fd后未关闭
22
+ void ProcessVulkanSemaphore(VkSemaphore semaphore)
23
+ {
24
+ int fd = GetFenceFdFromSemaphore(semaphore);
25
+ if (fd < 0) {
26
+ return; // 错误:fd未关闭
27
+ }
28
+ // 使用fd...
29
+ // 错误:函数结束时fd未关闭
30
+ }
31
+
32
+ // 错误示例2:多个退出路径遗漏关闭
33
+ int ExportAndUseFd(VkSemaphore sem)
34
+ {
35
+ int fd = vkGetSemaphoreFdKHR(device, sem, &info);
36
+ if (fd < 0) {
37
+ return -1;
38
+ }
39
+
40
+ if (!CheckCondition()) {
41
+ return -2; // 错误:fd未关闭
42
+ }
43
+
44
+ if (!ProcessFd(fd)) {
45
+ return -3; // 错误:fd未关闭
46
+ }
47
+
48
+ close(fd);
49
+ return 0;
50
+ }
51
+
52
+ // 错误示例3:异常分支fd泄漏
53
+ void HandleSemaphore(VkSemaphore sem)
54
+ {
55
+ int fd = GetFenceFdFromSemaphore(sem);
56
+
57
+ auto result = DoSomething(fd);
58
+ if (!result) {
59
+ LOGE("Operation failed");
60
+ return; // 错误:fd泄漏
61
+ }
62
+
63
+ close(fd);
64
+ }
65
+
66
+ // 错误示例4:导出fd后未立刻用智能指针管理
67
+ void DelayedFenceWrap(VkSemaphore sem)
68
+ {
69
+ int fd = GetFenceFdFromSemaphore(sem);
70
+ if (fd < 0) {
71
+ return;
72
+ }
73
+
74
+ // 错误:在创建智能指针之前插入了其他代码
75
+ DoSomeOtherWork(); // 如果这里抛异常或出错,fd会泄漏
76
+
77
+ // 虽然后续使用了智能指针,但不是"立刻"创建
78
+ sptr<SyncFence> fence = new SyncFence(fd);
79
+ }
80
+ ```
81
+
82
+ ### 正确示例
83
+
84
+ ```cpp
85
+ // 正确示例1:使用SyncFence智能指针管理fd生命周期
86
+ void ProcessVulkanSemaphore(VkSemaphore semaphore)
87
+ {
88
+ int fd = GetFenceFdFromSemaphore(semaphore);
89
+ if (fd < 0) {
90
+ LOGE("GetFenceFdFromSemaphore failed, fd=%{public}d", fd);
91
+ return;
92
+ }
93
+
94
+ // 正确:判断fd合法后,立刻(无中间代码)使用sptr<SyncFence>智能指针管理fd
95
+ sptr<SyncFence> fence = new SyncFence(fd);
96
+ // fd现在由fence管理,无需手动close
97
+ }
98
+
99
+ // 正确示例2:所有退出路径都正确关闭fd
100
+ int ExportAndUseFd(VkSemaphore sem)
101
+ {
102
+ int fd = vkGetSemaphoreFdKHR(device, sem, &info);
103
+ if (fd < 0) {
104
+ LOGE("vkGetSemaphoreFdKHR failed, fd=%{public}d", fd);
105
+ return -1;
106
+ }
107
+
108
+ // 正确:使用RAII方式管理fd
109
+ auto fdGuard = [](int* fd) { if (*fd >= 0) close(*fd); };
110
+ std::unique_ptr<int, decltype(fdGuard)> fdHolder(&fd, fdGuard);
111
+
112
+ if (!CheckCondition()) {
113
+ return -2; // fd会自动关闭
114
+ }
115
+
116
+ if (!ProcessFd(fd)) {
117
+ return -3; // fd会自动关闭
118
+ }
119
+
120
+ return 0;
121
+ }
122
+
123
+ // 正确示例3:使用SyncFence统一管理
124
+ void HandleSemaphore(VkSemaphore sem)
125
+ {
126
+ int fd = GetFenceFdFromSemaphore(sem);
127
+ if (fd < 0) {
128
+ LOGE("GetFenceFdFromSemaphore failed, fd=%{public}d", fd);
129
+ return;
130
+ }
131
+
132
+ // 正确:判断fd合法后,立刻(无中间代码)智能指针接管生命周期
133
+ sptr<SyncFence> fence = new SyncFence(fd);
134
+
135
+ auto result = DoSomething(fd);
136
+ if (!result) {
137
+ LOGE("Operation failed");
138
+ return; // 正确:fence析构时自动关闭fd
139
+ }
140
+ }
141
+ ```
142
+
143
+ ## 检测范围
144
+
145
+ 检查以下API/函数/模式:
146
+
147
+ - `GetFenceFdFromSemaphore()`、`vkGetSemaphoreFdKHR()`
148
+ - `GetSemaphoreFd()`、`ImportSemaphoreFdKHR()`
149
+ - 所有从Vulkan信号量导出fd的接口
150
+
151
+ ## 检测要点
152
+
153
+ 1. 识别从Vulkan信号量导出fd的调用
154
+ 2. **检查导出的fd是否在判断合法后立刻(无中间代码)被SyncFence智能指针管理**
155
+ - **关键检测点:** 从fd导出到创建智能指针之间,是否存在其他代码语句
156
+ - **违规示例:** fd导出 → 判断合法 → 中间有其他代码 → 创建智能指针 (应报错)
157
+ - **合规示例:** fd导出 → 判断合法 → 立即创建智能指针 (正确)
158
+ 3. 若未使用智能指针,检查所有退出路径是否都正确关闭fd
159
+ 4. 重点关注异常分支、提前返回、错误处理等场景
160
+ 5. **特别强调:** "立刻"意味着在获取有效fd后,下一行代码就应该创建智能指针,不允许在中间插入任何业务逻辑代码
161
+
162
+ ## 风险流分析(RiskFlow)
163
+
164
+ - **RISK_SOURCE**: 从Vulkan信号量导出fd后未**立刻**用智能指针管理生命周期
165
+ - **RISK_TYPE**: 文件描述符泄漏
166
+ - **RISK_PATH**: fd导出 → 未**立刻**用智能指针管理 → 中间代码异常 → fd泄漏累积
167
+ - **IMPACT_POINT**: 系统fd资源耗尽,导致无法打开新文件/设备
168
+
169
+ ## 影响分析(ImpactAnalysis)
170
+
171
+ - **Trigger**: 调用GetFenceFdFromSemaphore等接口导出fd
172
+ - **Propagation**: fd未**立刻**用智能指针管理,判断合法和创建智能指针之间插入其他代码,异常分支遗漏关闭
173
+ - **Consequence**: fd泄漏累积,系统资源耗尽,程序崩溃或功能异常
174
+ - **Mitigation**: 在判断fd合法后**立刻**(无任何中间代码)用sptr<SyncFence>智能指针管理fd生命周期
175
+
176
+ ## 误报排除
177
+
178
+ | 场景 | 识别特征 | 处理方式 |
179
+ |------|----------|----------|
180
+ | fd立即传递给其他函数管理 | fd作为参数传递给接管函数 | 不报 |
181
+ | 使用RAII类管理fd | unique_ptr/shared_ptr/sptr包裹 | 不报(但需检查是否**立刻**创建) |
182
+ | 有明确的close调用 | 所有退出路径都有close(fd) | 不报 |
183
+ | fd所有权转移 | 有注释说明fd所有权转移 | 不报 |
184
+
185
+ **注意:** 即使使用了智能指针管理,如果在判断fd合法后到创建智能指针之间插入了其他代码语句,仍应报错,因为这违反了"立刻"的要求。
186
+
187
+ ## 测试用例
188
+
189
+ ### 触发用例(应该报)
190
+
191
+ ```cpp
192
+ // test_StabilityCodeReview_GraphicsStability_011_trigger.cpp
193
+ void TriggerFdLeak(VkSemaphore semaphore)
194
+ {
195
+ int fd = GetFenceFdFromSemaphore(semaphore);
196
+ if (fd < 0) {
197
+ return; // 应该报:未使用智能指针,异常分支未关闭fd
198
+ }
199
+
200
+ // 使用fd...
201
+ // 应该报:函数结束未关闭fd
202
+ }
203
+ ```
204
+
205
+ ### 安全用例(不应该报)
206
+
207
+ ```cpp
208
+ // test_StabilityCodeReview_GraphicsStability_011_safe.cpp
209
+ void SafeFdManagement(VkSemaphore semaphore)
210
+ {
211
+ int fd = GetFenceFdFromSemaphore(semaphore);
212
+ if (fd < 0) {
213
+ LOGE("GetFenceFdFromSemaphore failed, fd=%{public}d", fd);
214
+ return; // 不报:fd无效,打印日志后返回
215
+ }
216
+
217
+ // 不报:判断fd合法后,立刻(无中间代码)使用智能指针管理fd
218
+ sptr<SyncFence> fence = new SyncFence(fd);
219
+ // fd由fence管理,自动关闭
220
+ }
221
+ ```