1# Subscribing to Address Sanitizer Events (C/C++)
2
3## **Available APIs**
4
5For details about how to use the APIs (such as parameter usage restrictions and value ranges), see [HiAppEvent](../reference/apis-performance-analysis-kit/_hi_app_event.md#hiappevent).
6
7**Subscription APIs**:
8
9| **API**                                                      | **Description**                                        |
10| ------------------------------------------------------------ | -------------------------------------------- |
11| int OH_HiAppEvent_AddWatcher (HiAppEvent_Watcher \*watcher)   | Adds a watcher to listen for application events.|
12| int OH_HiAppEvent_RemoveWatcher (HiAppEvent_Watcher \*watcher) | Removes a watcher for the specified application events.|
13
14## **How to Develop**
15
16The following describes how to subscribe an address sanitizer event for an array bounds write.
17
181. Create a native C++ project and import the **jsoncpp** file to the project. The directory structure is as follows:
19
20   ```yml
21   entry:
22     src:
23       main:
24         cpp:
25           - json:
26               - json.h
27               - json-forwards.h
28           - types:
29               libentry:
30                 - index.d.ts
31           - CMakeLists.txt
32           - napi_init.cpp
33           - jsoncpp.cpp
34         ets:
35           - entryability:
36               - EntryAbility.ets
37           - pages:
38               - Index.ets
39   ```
40
412. In the **CMakeLists.txt** file, add the source file and dynamic libraries.
42
43   ```cmake
44   # Add the jsoncpp.cpp file, which is used to parse the JSON strings in the subscription events.
45   add_library(entry SHARED napi_init.cpp jsoncpp.cpp)
46   # Add libhiappevent_ndk.z.so and libhilog_ndk.z.so (log output).
47   target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libhiappevent_ndk.z.so)
48   ```
49
503. Import the dependencies to the **napi_init.cpp** file, and define **LOG_TAG**.
51
52   ```c++
53   #include "napi/native_api.h"
54   #include "json/json.h"
55   #include "hilog/log.h"
56   #include "hiappevent/hiappevent.h"
57
58   #undef LOG_TAG
59   #define LOG_TAG "testTag"
60   ```
61
624. Subscribe to system events.
63
64   - Watcher of the onReceive type:
65
66     In the **napi_init.cpp** file, define the methods related to the watcher of the onReceive type.
67
68     ```c++
69     // Define a variable to cache the pointer to the created watcher.
70     static HiAppEvent_Watcher *systemEventWatcher;
71
72     static void OnReceive(const char *domain, const struct HiAppEvent_AppEventGroup *appEventGroups, uint32_t groupLen) {
73         for (int i = 0; i < groupLen; ++i) {
74             for (int j = 0; j < appEventGroups[i].infoLen; ++j) {
75                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", appEventGroups[i].appEventInfos[j].domain);
76                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", appEventGroups[i].appEventInfos[j].name);
77                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", appEventGroups[i].appEventInfos[j].type);
78                 if (strcmp(appEventGroups[i].appEventInfos[j].domain, DOMAIN_OS) == 0 &&
79                     strcmp(appEventGroups[i].appEventInfos[j].name, EVENT_ADDRESS_SANITIZER) == 0) {
80                     Json::Value params;
81                     Json::Reader reader(Json::Features::strictMode());
82                     Json::FastWriter writer;
83                     if (reader.parse(appEventGroups[i].appEventInfos[j].params, params)) {
84                         auto time = params["time"].asInt64();
85                         auto bundleVersion = params["bundle_version"].asString();
86                         auto bundleName = params["bundle_name"].asString();
87                         auto pid = params["pid"].asInt();
88                         auto uid = params["uid"].asInt();
89                         auto type = params["type"].asString();
90                         auto boolFlag = params["log_over_limit"].asBool();
91                         std::string logOverLimit = params["log_over_limit"].asBool() ? "true" : "false";
92                         auto externalLog = writer.write(params["external_log"]);
93                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time);
94                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", bundleVersion.c_str());
95                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str());
96                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid);
97                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid);
98                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.type=%{public}s", type.c_str());
99                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", externalLog.c_str());
100                         OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}s", logOverLimit.c_str());
101                     }
102                 }
103             }
104         }
105     }
106
107     static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
108         // Set the watcher name. The system identifies different watchers based on their names.
109         systemEventWatcher = OH_HiAppEvent_CreateWatcher("onReceiverWatcher");
110         // Set the event to subscribe to EVENT_ADDRESS_SANITIZER.
111         const char *names[] = {EVENT_ADDRESS_SANITIZER};
112         // Add the events to watch, for example, system events.
113         OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1);
114         // Set the implemented callback. After receiving the event, the watcher immediately triggers the OnReceive callback.
115         OH_HiAppEvent_SetWatcherOnReceive(systemEventWatcher, OnReceive);
116         // Add a watcher to listen for the specified event.
117         OH_HiAppEvent_AddWatcher(systemEventWatcher);
118         return {};
119     }
120     ```
121
122   - Watcher of the onTrigger type:
123
124     In the **napi_init.cpp** file, define the methods related to the watcher of the OnTrigger type.
125
126     ```c++
127     // Define a variable to cache the pointer to the created watcher.
128     static HiAppEvent_Watcher *systemEventWatcher;
129
130     // Implement the callback function used to return the listened events. The content pointed by the events pointer is valid only in this function.
131     static void OnTake(const char *const *events, uint32_t eventLen) {
132         Json::Reader reader(Json::Features::strictMode());
133         Json::FastWriter writer;
134         for (int i = 0; i < eventLen; ++i) {
135             Json::Value eventInfo;
136             if (reader.parse(events[i], eventInfo)) {
137                 auto domain =  eventInfo["domain_"].asString();
138                 auto name = eventInfo["name_"].asString();
139                 auto type = eventInfo["type_"].asInt();
140                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.domain=%{public}s", domain.c_str());
141                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.name=%{public}s", name.c_str());
142                 OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.eventType=%{public}d", type);
143                 if (domain ==  DOMAIN_OS && name == EVENT_ADDRESS_SANITIZER) {
144                     auto time = eventInfo["time"].asInt64();
145                     auto bundleVersion = eventInfo["bundle_version"].asString();
146                     auto bundleName = eventInfo["bundle_name"].asString();
147                     auto pid = eventInfo["pid"].asInt();
148                     auto uid = eventInfo["uid"].asInt();
149                     auto asanType = eventInfo["type"].asString();
150                     auto externalLog = writer.write(eventInfo["external_log"]);
151                     std::string logOverLimit = eventInfo["log_over_limit"].asBool() ? "true" : "false";
152                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.time=%{public}lld", time);
153                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_version=%{public}s", bundleVersion.c_str());
154                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.bundle_name=%{public}s", bundleName.c_str());
155                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.pid=%{public}d", pid);
156                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.uid=%{public}d", uid);
157                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.crash_type=%{public}s", asanType.c_str());
158                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.external_log=%{public}s", externalLog.c_str());
159                     OH_LOG_INFO(LogType::LOG_APP, "HiAppEvent eventInfo.params.log_over_limit=%{public}s", logOverLimit.c_str());
160                 }
161             }
162         }
163     }
164
165     // Implement the subscription callback function to apply custom processing to the obtained event logging data.
166     static void OnTrigger(int row, int size) {
167         // After the callback is received, obtain the specified number of received events.
168         OH_HiAppEvent_TakeWatcherData(systemEventWatcher, row, OnTake);
169     }
170
171     static napi_value RegisterWatcher(napi_env env, napi_callback_info info) {
172         // Set the watcher name. The system identifies different watchers based on their names.
173         systemEventWatcher = OH_HiAppEvent_CreateWatcher("onTriggerWatcher");
174         // Set the event to subscribe to EVENT_ADDRESS_SANITIZER.
175         const char *names[] = {EVENT_ADDRESS_SANITIZER};
176         // Add the events to watch, for example, system events.
177         OH_HiAppEvent_SetAppEventFilter(systemEventWatcher, DOMAIN_OS, 0, names, 1);
178         // Set the implemented callback function. The callback function will be triggered when the conditions set by OH_HiAppEvent_SetTriggerCondition are met.
179         OH_HiAppEvent_SetWatcherOnTrigger(systemEventWatcher, OnTrigger);
180         // Set the conditions for triggering the subscription callback. For example, trigger this onTrigger callback when the number of new event logs is 1.
181         OH_HiAppEvent_SetTriggerCondition(systemEventWatcher, 1, 0, 0);
182         // Add a watcher to listen for the specified event.
183         OH_HiAppEvent_AddWatcher(systemEventWatcher);
184         return {};
185     }
186     ```
187
1885. Construct an address out-of-bounds error.
189
190   In the **napi_init.cpp** file, define a **Test** method to perform out-of-bounds access on an integer array.
191
192   ```c++
193   static napi_value Test(napi_env env, napi_callback_info info)
194   {
195       int a[10];
196       a[10] = 1;
197       return {};
198   }
199   ```
200
2016. Register **RegisterWatcher** and **Test** as ArkTS APIs.
202
203   In the **napi_init.cpp** file, register **RegisterWatcher** and **Test** as ArkTS APIs.
204
205   ```c++
206   static napi_value Init(napi_env env, napi_value exports)
207   {
208       napi_property_descriptor desc[] = {
209           { "registerWatcher", nullptr, RegisterWatcher, nullptr, nullptr, nullptr, napi_default, nullptr },
210           { "test", nullptr, Test, nullptr, nullptr, nullptr, napi_default, nullptr}
211       };
212       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
213       return exports;
214   }
215   ```
216
217   In the **index.d.ts** file, define ArkTS APIs.
218
219   ```typescript
220   export const registerWatcher: () => void;
221   export const test: () => void;
222   ```
223
2247. In the **EntryAbility.ets** file, add the following interface invocation to **onCreate()**.
225
226   ```typescript
227   // Import the dependent module.
228   import testNapi from 'libentry.so'
229
230   // Add the interface invocation to onCreate().
231   // Register the system event watcher at startup.
232   testNapi.registerWatcher();
233   ```
234
2358. In the **entry/src/main/ets/pages/Index.ets** file, add a button to trigger the address sanitizer event.
236
237   ```ts
238   import testNapi from 'libentry.so'
239
240   @Entry
241   @Component
242   struct Index {
243     build() {
244       Row() {
245         Column() {
246           Button("address-sanitizer").onClick(() => {
247             testNapi.test();
248           })
249         }
250         .width('100%')
251       }
252       .height('100%')
253     }
254   }
255   ```
256
2579. In DevEco Studio, choose **entry**, click **Edit Configurations**, click **Diagnostics**, select **Address Sanitizer**, and click **OK**. Click the **Run** button to run the project. Then, click the **address-sanitizer** button to trigger an address sanitizer event. The application crashes. After restarting the application, you can view the following event information in the **Log** window.
258
259   ```text
260   HiAppEvent eventInfo.domain=OS
261   HiAppEvent eventInfo.name=ADDRESS_SANITIZER
262   HiAppEvent eventInfo.eventType=1
263   HiAppEvent eventInfo.params.time=1713148093326
264   HiAppEvent eventInfo.params.bundle_version=1.0.0
265   HiAppEvent eventInfo.params.bundle_name=com.example.myapplication
266   HiAppEvent eventInfo.params.pid=3378
267   HiAppEvent eventInfo.params.uid=20020140
268   HiAppEvent eventInfo.params.type="stack-buffer-overflow"
269   HiAppEvent eventInfo.params.external_log=["/data/storage/el2/log/hiappevent/ADDRESS_SANITIZER_1713148093326_3378.log"]
270   HiAppEvent eventInfo.params.log_over_limit=false
271   ```
272
27310. Remove the event watcher.
274
275    ```c++
276    static napi_value RemoveWatcher(napi_env env, napi_callback_info info) {
277        // Remove the watcher.
278        OH_HiAppEvent_RemoveWatcher(systemEventWatcher);
279        return {};
280    }
281    ```
282
28311. Destroy the event watcher.
284
285    ```c++
286    static napi_value DestroyWatcher(napi_env env, napi_callback_info info) {
287        // Destroy the created watcher and set systemEventWatcher to nullptr.
288        OH_HiAppEvent_DestroyWatcher(systemEventWatcher);
289        systemEventWatcher = nullptr;
290        return {};
291    }
292    ```
293