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