| @@ -872,7 +872,7 @@ static bool IsPidExist(ProxyBaseInfo *baseInfo, uint32_t requestId, pid_t pid) | |||
| 872 | Anonymize(baseInfo->uuid, &uuidTmp); | 872 | Anonymize(baseInfo->uuid, &uuidTmp); |
| 873 | TRANS_LOGI(TRANS_SVC, | 873 | TRANS_LOGI(TRANS_SVC, |
| 874 | "[br_proxy] brproxy open! brMac=%{public}s, uuid=%{public}s, requestId=%{public}u, pid=%{public}d", | 874 | "[br_proxy] brproxy open! brMac=%{public}s, uuid=%{public}s, requestId=%{public}u, pid=%{public}d", |
| 875 | - BrMacTmp, uuidTmp, requestId, pid); | 875 | + AnonymizeWrapper(BrMacTmp), AnonymizeWrapper(uuidTmp), requestId, pid); |
AnonymizeWrapper(BrMacTmp) 和 AnonymizeWrapper(uuidTmp) 的返回值未释放。BrMacTmp 和 uuidTmp 已通过 Anonymize 分配内存,如果 AnonymizeWrapper 内部也分配内存(如内部调用 Anonymize 并返回结果),则每次执行此代码路径都会泄漏两块内存。此外,对已匿名化的字符串再次调用匿名化包装器属于逻辑错误(双重匿名化),可能产生异常输出。 确认 AnonymizeWrapper 的实现。如果它分配内存,需在日志输出后释放其返回值;如果其设计用途是处理原始字符串,应直接传入 baseInfo->brMac 和 baseInfo->uuid,而非已匿名化的 BrMacTmp/uuidTmp。 ![]() ![]() AnonymizeWrapper(BrMacTmp) 和 AnonymizeWrapper(uuidTmp) 的返回值未被释放。原代码直接使用已 Anonymize 的字符串并通过 AnonymizeFree 释放,新代码用 AnonymizeWrapper 包装后,若该函数内部分配了新内存,则返回值会泄漏。 确认 AnonymizeWrapper 的实现。若其分配内存,需在日志输出后释放返回值;若返回内部静态/栈缓冲区则无需处理。 ![]() ![]() AnonymizeWrapper(BrMacTmp) 和 AnonymizeWrapper(uuidTmp) 可能分配新内存,但后续仅 AnonymizeFree(BrMacTmp) 和 AnonymizeFree(uuidTmp) 释放了原始内存。如果 AnonymizeWrapper 内部分配了新字符串,则该内存永远不会被释放,导致内存泄漏。 确认 AnonymizeWrapper 的实现。如果它分配新内存,需要保存其返回值并在日志输出后释放;如果它只是返回输入指针的包装,则无需额外释放。或者直接使用 AnonymizeWrapper 替代 Anonymize+AnonymizeFree 模式,移除冗余调用。 ![]() ![]() | |||
| 876 | AnonymizeFree(BrMacTmp); | 876 | AnonymizeFree(BrMacTmp); |
| 877 | AnonymizeFree(uuidTmp); | 877 | AnonymizeFree(uuidTmp); |
| 878 | (void)SoftBusMutexUnlock(&(g_serverList->lock)); | 878 | (void)SoftBusMutexUnlock(&(g_serverList->lock)); |
| @@ -1305,7 +1305,8 @@ static int32_t RefreshChannel(ProxyChannelParam *param, bool *isRefresh, uint32_ | |||
| 1305 | BrProxyInfo *nodeNext = NULL; | 1305 | BrProxyInfo *nodeNext = NULL; |
| 1306 | LIST_FOR_EACH_ENTRY_SAFE(nodeInfo, nodeNext, &(g_proxyList->list), BrProxyInfo, node) { | 1306 | LIST_FOR_EACH_ENTRY_SAFE(nodeInfo, nodeNext, &(g_proxyList->list), BrProxyInfo, node) { |
| 1307 | if (strcmp(nodeInfo->proxyInfo.brMac, param->brMac) != 0 || | 1307 | if (strcmp(nodeInfo->proxyInfo.brMac, param->brMac) != 0 || |
| 1308 | - strcmp(nodeInfo->proxyInfo.uuid, param->uuid) != 0) { | 1308 | + strcmp(nodeInfo->proxyInfo.uuid, param->uuid) != 0 || |
RefreshChannel 中新增了 nodeInfo->requestId != requestId 的匹配条件。这会阻止对同一设备(相同 brMac+uuid)但不同 requestId 的已有通道进行刷新,可能导致无法复用已有连接、创建重复通道或连接失败。 确认此变更是否符合预期。如果 RefreshChannel 的目的是刷新同一设备的已有通道,则不应添加 requestId 匹配条件;如果需要精确匹配特定请求的通道,需确保调用方传入正确的 requestId。 ![]() ![]() RefreshChannel 中新增了 nodeInfo->requestId != requestId 的条件判断。如果 requestId 是 param->requestId(新请求ID),则此条件会导致所有已有通道(具有不同的旧 requestId)都被跳过,使 RefreshChannel 永远无法匹配到已有通道,导致每次都创建新通道而非复用已有通道,可能造成资源泄漏或连接管理混乱。 确认 requestId 变量的来源。如果意图是匹配旧通道进行刷新,应使用 oldRequestId 而非新的 requestId 进行比较;如果是有意限制只刷新相同 requestId 的通道,需确认此行为变更不会导致已有通道无法被刷新。 ![]() ![]() | |||
| 1309 | + nodeInfo->requestId != requestId) { | ||
| 1309 | continue; | 1310 | continue; |
| 1310 | } | 1311 | } |
| 1311 | if (nodeInfo->isConnected && nodeInfo->channel.refresh != NULL) { | 1312 | if (nodeInfo->isConnected && nodeInfo->channel.refresh != NULL) { |
| @@ -1322,7 +1323,6 @@ static int32_t RefreshChannel(ProxyChannelParam *param, bool *isRefresh, uint32_ | |||
| 1322 | static int32_t InitProxyChannelParams(const char *brMac, const char *uuid, | 1323 | static int32_t InitProxyChannelParams(const char *brMac, const char *uuid, |
| 1323 | uint32_t requestId, int32_t appIndex, ProxyChannelParam *param) | 1324 | uint32_t requestId, int32_t appIndex, ProxyChannelParam *param) |
| 1324 | { | 1325 | { |
潜在的未初始化内存问题:memset_s 从 InitProxyChannelParams 中移除,改由调用方 ConnectPeerDevice 负责。如果存在其他调用 InitProxyChannelParams 的地方且未事先清零结构体,ProxyChannelParam 中未被显式赋值的字段将包含未初始化的栈内存,可能导致不可预期的行为。 确认 InitProxyChannelParams 的所有调用方都在调用前对 ProxyChannelParam 进行了清零操作;或者保留 InitProxyChannelParams 内部的 memset_s,确保函数自身的健壮性。 ![]() ![]() 从 InitProxyChannelParams 中移除了 memset_s 初始化。虽然 ConnectPeerDevice 调用前新增了 memset_s,但如果 InitProxyChannelParams 被其他函数调用且未事先清零 param 结构体,则 ProxyChannelParam 中未被显式赋值的字段将包含未初始化的栈数据,可能导致数据损坏或不可预期行为。 在 InitProxyChannelParams 内部保留 memset_s 初始化,确保无论调用方是否预清零,结构体所有字段都处于已知状态。 ![]() ![]() 从 InitProxyChannelParams 中移除了 memset_s 初始化。该函数是 static 函数,如果文件中存在其他调用者(未在 diff 中显示),它们将传入未清零的 ProxyChannelParam 结构体,导致未初始化字段被后续逻辑读取,可能引发数据损坏或未定义行为。即使当前唯一调用者 ConnectPeerDevice 已补充了 memset_s,这种将初始化责任转移到调用者的模式也是脆弱的。 在 InitProxyChannelParams 函数内部保留 memset_s 初始化,确保函数自身契约完整,不依赖调用者预先清零。 ![]() ![]() 从 InitProxyChannelParams 中移除了 memset_s 对 param 结构体的整体清零。该函数为 static,若存在除 ConnectPeerDevice 之外的其他调用者未在调用前执行 memset_s,ProxyChannelParam 中未显式赋值的字段将为未初始化状态,可能导致未定义行为或数据损坏。 确认 InitProxyChannelParams 的所有调用点均在调用前对 ProxyChannelParam 进行了 memset_s 清零。若有遗漏调用者,需补充清零操作或将 memset_s 保留在函数内部。 ![]() ![]() 从 InitProxyChannelParams 中移除了 memset_s 对 param 的清零操作。虽然当前唯一可见的调用方 ConnectPeerDevice 在调用前添加了 memset_s,但如果存在其他调用方未初始化该结构体,ProxyChannelParam 中未被显式赋值的字段将包含未初始化的栈数据,可能导致未定义行为或数据泄露。 在 InitProxyChannelParams 函数内部保留 memset_s 清零操作以确保防御性安全,或者确保所有调用方在调用前都正确初始化 ProxyChannelParam 结构体。 ![]() ![]() | |||
| 1325 | - (void)memset_s(param, sizeof(ProxyChannelParam), 0, sizeof(ProxyChannelParam)); | ||
| 1326 | param->requestId = requestId; | 1326 | param->requestId = requestId; |
| 1327 | param->appIndex = appIndex; | 1327 | param->appIndex = appIndex; |
| 1328 | TransBrProxyStorageInfo info; | 1328 | TransBrProxyStorageInfo info; |
| @@ -1335,7 +1335,7 @@ static int32_t InitProxyChannelParams(const char *brMac, const char *uuid, | |||
| 1335 | if (strcpy_s(param->brMac, sizeof(param->brMac), brMac) != EOK || | 1335 | if (strcpy_s(param->brMac, sizeof(param->brMac), brMac) != EOK || |
| 1336 | strcpy_s(param->uuid, sizeof(param->uuid), uuid) != EOK) { | 1336 | strcpy_s(param->uuid, sizeof(param->uuid), uuid) != EOK) { |
| 1337 | TRANS_LOGE(TRANS_SVC, "[br_proxy] copy brMac or uuid failed"); | 1337 | TRANS_LOGE(TRANS_SVC, "[br_proxy] copy brMac or uuid failed"); |
| 1338 | - return SOFTBUS_MEM_ERR; | 1338 | + return SOFTBUS_STRCPY_ERR; |
| 1339 | } | 1339 | } |
| 1340 | param->timeoutMs = BR_PROXY_MAX_WAIT_TIME_MS; | 1340 | param->timeoutMs = BR_PROXY_MAX_WAIT_TIME_MS; |
| 1341 | return SOFTBUS_OK; | 1341 | return SOFTBUS_OK; |
| @@ -1359,15 +1359,21 @@ static int32_t AddChannelAndRefresh(ProxyChannelParam *param, uint32_t oldReques | |||
| 1359 | } | 1359 | } |
| 1360 | if (!isRefresh) { | 1360 | if (!isRefresh) { |
| 1361 | ProxyChannelManager *proxyMgr = GetProxyChannelManager(); | 1361 | ProxyChannelManager *proxyMgr = GetProxyChannelManager(); |
| 1362 | + if (proxyMgr == NULL) { | ||
| 1363 | + ret = SOFTBUS_INVALID_PARAM; | ||
| 1364 | + goto FAIL; | ||
在 AddChannelAndRefresh 函数中,当 proxyMgr == NULL 时跳转到 FAIL 标签,但此时 ret 仍为之前 RefreshChannel 调用成功后的值(SOFTBUS_OK),导致函数在失败路径上返回成功码。调用方会误认为操作成功,后续可能访问未初始化的 channel 资源。 在 goto FAIL 之前设置 ret 为适当的错误码,例如:ret = SOFTBUS_ERR; goto FAIL; ![]() ![]() 在 AddChannelAndRefresh 函数中,当 在 ![]() ![]() | |||
| 1365 | + } | ||
逻辑错误:当 GetProxyChannelManager() 返回 NULL 时,直接 goto FAIL,但此时 ret 变量未被设置为错误码(可能仍为之前 RefreshChannel 返回的 SOFTBUS_OK)。这导致函数在失败路径上返回 SOFTBUS_OK,调用方会误认为操作成功。同时 FAIL 标签处会执行 UpdateBrProxyRequestId 和 ServerDeleteChannelFromList 清理操作,但此时 proxyMgr 为 NULL,channel 可能尚未被正确创建,这些清理操作可能不安全。 在 goto FAIL 之前设置 ret 为适当的错误码,例如:if (proxyMgr == NULL) { ret = SOFTBUS_ERR; goto FAIL; } ![]() ![]() | |||
| 1362 | ret = proxyMgr->openProxyChannel(param, &g_channelOpen); | 1366 | ret = proxyMgr->openProxyChannel(param, &g_channelOpen); |
| 1363 | if (ret != SOFTBUS_OK) { | 1367 | if (ret != SOFTBUS_OK) { |
| 1364 | - TRANS_LOGE(TRANS_SVC, "[br_proxy] openProxyChannel failed, ret=%{public}d", ret); | 1368 | + goto FAIL; |
| 1365 | - (void)UpdateBrProxyRequestId(param->brMac, param->uuid, param->appIndex, oldRequestId, &oldRequestId); | ||
| 1366 | - (void)ServerDeleteChannelFromList(channelId); | ||
| 1367 | - return ret; | ||
| 1368 | } | 1369 | } |
| 1369 | } | 1370 | } |
| 1370 | return ret; | 1371 | return ret; |
| 1372 | +FAIL: | ||
| 1373 | + TRANS_LOGE(TRANS_SVC, "[br_proxy] openProxyChannel failed, ret=%{public}d", ret); | ||
| 1374 | + (void)UpdateBrProxyRequestId(param->brMac, param->uuid, param->appIndex, oldRequestId, &oldRequestId); | ||
| 1375 | + (void)ServerDeleteChannelFromList(channelId); | ||
| 1376 | + return ret; | ||
| 1371 | } | 1377 | } |
| 1372 | 1378 | ||
| 1373 | static int32_t ConnectPeerDevice(const char *brMac, const char *uuid, uint32_t *requestId, int32_t appIndex) | 1379 | static int32_t ConnectPeerDevice(const char *brMac, const char *uuid, uint32_t *requestId, int32_t appIndex) |
| @@ -1378,6 +1384,7 @@ static int32_t ConnectPeerDevice(const char *brMac, const char *uuid, uint32_t * | |||
| 1378 | } | 1384 | } |
| 1379 | *requestId = proxyMgr->generateRequestId(); | 1385 | *requestId = proxyMgr->generateRequestId(); |
| 1380 | ProxyChannelParam param; | 1386 | ProxyChannelParam param; |
| 1387 | + (void)memset_s(¶m, sizeof(ProxyChannelParam), 0, sizeof(ProxyChannelParam)); | ||
lgtm ![]() ![]() | |||
| 1381 | int32_t ret = InitProxyChannelParams(brMac, uuid, *requestId, appIndex, ¶m); | 1388 | int32_t ret = InitProxyChannelParams(brMac, uuid, *requestId, appIndex, ¶m); |
| 1382 | if (ret != SOFTBUS_OK) { | 1389 | if (ret != SOFTBUS_OK) { |
| 1383 | return ret; | 1390 | return ret; |
| @@ -14,6 +14,8 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include "far_field_proxy_adapter.h" | 16 | #include "far_field_proxy_adapter.h" |
| 17 | + | ||
| 18 | +#include "conn_event.h" | ||
| 17 | #include "conn_log.h" | 19 | #include "conn_log.h" |
| 18 | #include "softbus_error_code.h" | 20 | #include "softbus_error_code.h" |
| 19 | #include "softbus_init_common.h" | 21 | #include "softbus_init_common.h" |
| @@ -61,6 +63,36 @@ static FarFieldCallbackSt *g_farFieldCallback = NULL; | |||
| 61 | 63 | ||
| 62 | static SoftBusMutex g_adapterMutex; | 64 | static SoftBusMutex g_adapterMutex; |
| 63 | 65 | ||
| 66 | +typedef int32_t (*DfxEventCallbackFunc)(const DfxEventExtra *event); | ||
| 67 | +typedef void (*RegisterDfxEventCallbackFunc)(DfxEventCallbackFunc callback); | ||
| 68 | + | ||
| 69 | +static int32_t DfxEventCallback(const DfxEventExtra *event) | ||
| 70 | +{ | ||
| 71 | + CONN_CHECK_AND_RETURN_RET_LOGE(event != NULL, SOFTBUS_INVALID_PARAM, CONN_PROXY, "event is null"); | ||
DfxEventCallback 中未对 event->func 和 event->hostPkg 指针进行 NULL 检查。如果这些指针为 NULL 且 ConnEventInner 内部未做防御性处理,可能导致空指针解引用崩溃。 在调用 ConnEventInner 前,对 event->func 和 event->hostPkg 进行 NULL 检查,或确保 ConnEventInner 能够安全处理 NULL 指针参数。 ![]() ![]() | |||
| 72 | + ConnEventExtra extra = { | ||
| 73 | + .callerPkg = event->hostPkg, | ||
在 DfxEventCallback 中,未对 event->hostPkg 和 event->func 进行非空校验。如果外部库传入的这两个字段为 NULL,且 ConnEventInner 或其下游函数直接使用这些字符串指针(如 strlen、printf 等),可能导致空指针解引用崩溃。 在使用 event->hostPkg 和 event->func 之前增加非空校验,或确保 ConnEventInner 内部能安全处理 NULL 字符串。 ![]() ![]() | |||
| 74 | + .result = event->stageRes, | ||
| 75 | + .errcode = event->errorCode, | ||
| 76 | + .connectReason = event->connectReason, | ||
| 77 | + .costTime = event->costTime, | ||
| 78 | + .sendCnt = event->sendMsgCnt, | ||
DfxEventCallback 函数中直接使用 event->hostPkg 和 event->func,未检查它们是否为 NULL。如果这些指针为 NULL,且下游函数 ConnEventInner 未做空指针检查,可能导致空指针解引用崩溃。 在使用 event->hostPkg 和 event->func 前增加非空检查,或确保下游函数能安全处理 NULL 指针。 ![]() ![]() | |||
| 79 | + .receiveCnt = event->receiveMsgCnt, | ||
| 80 | + }; | ||
| 81 | + ConnEventInner(event->bizScene, event->bizStage, event->func, event->line, &extra); | ||
| 82 | + return SOFTBUS_OK; | ||
| 83 | +} | ||
RegisterDfxEventCallback 函数直接访问全局变量 g_adapterContext.soHandle 但未获取 g_adapterMutex 互斥锁。若 LoadFarFieldSymbols 的调用上下文未持有该锁,存在与 soHandle 相关的数据竞争风险。 在 RegisterDfxEventCallback 中访问 g_adapterContext.soHandle 前确保已持有 g_adapterMutex,或在 LoadFarFieldSymbols 调用链中确认锁已被持有。 ![]() ![]() | |||
| 84 | + | ||
dlsym 调用后仅通过判断返回值是否为 NULL 来检测错误。dlsym 返回 NULL 既可能表示符号未找到,也可能是符号的合法值。未使用 dlerror() 进行区分,在边缘场景下可能误判。 在调用 dlsym 前先调用 dlerror() 清除之前的错误状态,调用后再检查 dlerror() 返回值以准确判断是否发生错误。 ![]() ![]() RegisterDfxEventCallback 函数中调用 dlsym 时未检查 g_adapterContext.soHandle 是否为 NULL。如果 soHandle 为 NULL,dlsym 可能会在主程序中搜索符号,导致调用错误的函数或引发未定义行为。 在调用 dlsym 前增加对 g_adapterContext.soHandle != NULL 的检查。 ![]() ![]() RegisterDfxEventCallback 访问全局变量 g_adapterContext.soHandle 时未持有 g_adapterMutex。如果 LoadFarFieldSymbols 在多线程环境下被调用,或与 so 卸载操作并发,可能导致竞态条件。 确保在持有 g_adapterMutex 的情况下调用 RegisterDfxEventCallback 或访问 g_adapterContext。 ![]() ![]() | |||
| 85 | +static void RegisterDfxEventCallback(void) | ||
| 86 | +{ | ||
| 87 | + RegisterDfxEventCallbackFunc registerDfxEventCallback = (RegisterDfxEventCallbackFunc)dlsym( | ||
| 88 | + g_adapterContext.soHandle, "RegisterDfxEventCallback"); | ||
| 89 | + if (registerDfxEventCallback == NULL) { | ||
| 90 | + CONN_LOGE(CONN_PROXY, "Failed to load RegisterDfxEventCallback symbol"); | ||
| 91 | + return; | ||
| 92 | + } | ||
| 93 | + registerDfxEventCallback(DfxEventCallback); | ||
| 94 | +} | ||
| 95 | + | ||
| 64 | static int32_t LoadFarFieldSymbols(void) | 96 | static int32_t LoadFarFieldSymbols(void) |
| 65 | { | 97 | { |
| 66 | g_adapterContext.initProxy = (FarFieldInitProxyFunc)dlsym(g_adapterContext.soHandle, "FarFieldInitProxy"); | 98 | g_adapterContext.initProxy = (FarFieldInitProxyFunc)dlsym(g_adapterContext.soHandle, "FarFieldInitProxy"); |
| @@ -101,6 +133,7 @@ static int32_t LoadFarFieldSymbols(void) | |||
| 101 | CONN_CHECK_AND_RETURN_RET_LOGE(g_adapterContext.refresh != NULL, FAR_FIELD_ADAPTER_SYMBOL_NOT_FOUND, CONN_PROXY, | 133 | CONN_CHECK_AND_RETURN_RET_LOGE(g_adapterContext.refresh != NULL, FAR_FIELD_ADAPTER_SYMBOL_NOT_FOUND, CONN_PROXY, |
| 102 | "Failed to load FarFieldRefresh symbol"); | 134 | "Failed to load FarFieldRefresh symbol"); |
| 103 | 135 | ||
| 136 | + RegisterDfxEventCallback(); | ||
| 104 | CONN_LOGI(CONN_PROXY, "All symbols loaded successfully"); | 137 | CONN_LOGI(CONN_PROXY, "All symbols loaded successfully"); |
| 105 | return SOFTBUS_OK; | 138 | return SOFTBUS_OK; |
| 106 | } | 139 | } |
| @@ -106,8 +106,11 @@ CONN_ASSIGNER(Errcode, BrProxyState, brProxyState) | |||
| 106 | CONN_ASSIGNER(Errcode, BrProxyIsClear, brProxyIsClear) | 106 | CONN_ASSIGNER(Errcode, BrProxyIsClear, brProxyIsClear) |
| 107 | CONN_ASSIGNER(Errcode, BrProxyIsRetry, brProxyIsRetry) | 107 | CONN_ASSIGNER(Errcode, BrProxyIsRetry, brProxyIsRetry) |
| 108 | CONN_ASSIGNER(Errcode, BrProxyIsAcl, brProxyIsAcl) | 108 | CONN_ASSIGNER(Errcode, BrProxyIsAcl, brProxyIsAcl) |
| 109 | +CONN_ASSIGNER(Errcode, ConnectReason, connectReason) | ||
| 110 | +CONN_ASSIGNER(Errcode, SendCnt, sendCnt) | ||
| 111 | +CONN_ASSIGNER(Errcode, ReceiveCnt, receiveCnt) | ||
| 109 | 112 | ||
| 110 | -#define CONN_ASSIGNER_SIZE 72 // Size of g_connAssigners | 113 | +#define CONN_ASSIGNER_SIZE 75 // Size of g_connAssigners |
| 111 | static HiSysEventParamAssigner g_connAssigners[] = { | 114 | static HiSysEventParamAssigner g_connAssigners[] = { |
| 112 | { "STAGE_RES", HISYSEVENT_INT32, ConnAssignerResult }, | 115 | { "STAGE_RES", HISYSEVENT_INT32, ConnAssignerResult }, |
| 113 | { "ERROR_CODE", HISYSEVENT_INT32, ConnAssignerErrcode }, | 116 | { "ERROR_CODE", HISYSEVENT_INT32, ConnAssignerErrcode }, |
| @@ -172,15 +175,18 @@ static HiSysEventParamAssigner g_connAssigners[] = { | |||
| 172 | { "BUSINESS_TAG", HISYSEVENT_STRING, ConnAssignerBusinessTag }, | 175 | { "BUSINESS_TAG", HISYSEVENT_STRING, ConnAssignerBusinessTag }, |
| 173 | { "STA_CHLOAD", HISYSEVENT_INT32, ConnAssignerStaChload }, | 176 | { "STA_CHLOAD", HISYSEVENT_INT32, ConnAssignerStaChload }, |
| 174 | { "SAME_ACCOUNT", HISYSEVENT_INT32, ConnAssignerSameAccount }, | 177 | { "SAME_ACCOUNT", HISYSEVENT_INT32, ConnAssignerSameAccount }, |
| 175 | - { "DISCOVERY_CNT", HISYSEVENT_INT32, ConnAssignerDiscoveryCnt }, | 178 | + { "DISCOVERY_CNT", HISYSEVENT_INT32, ConnAssignerDiscoveryCnt }, |
| 176 | - { "CONNECTING_CNT", HISYSEVENT_INT32, ConnAssignerConnectingCnt }, | 179 | + { "CONNECTING_CNT", HISYSEVENT_INT32, ConnAssignerConnectingCnt }, |
| 177 | - { "CONNECT_SUCCESS_CNT", HISYSEVENT_INT32, ConnAssignerConnectSuccessCnt }, | 180 | + { "CONNECT_SUCCESS_CNT", HISYSEVENT_INT32, ConnAssignerConnectSuccessCnt }, |
| 178 | - { "CONNECT_FAIL_CNT", HISYSEVENT_INT32, ConnAssignerConnectFailCnt }, | 181 | + { "CONNECT_FAIL_CNT", HISYSEVENT_INT32, ConnAssignerConnectFailCnt }, |
| 179 | - { "VIRTUAL_LINK_TYPE", HISYSEVENT_INT32, ConnAssignerVirtualLinkType }, | 182 | + { "VIRTUAL_LINK_TYPE", HISYSEVENT_INT32, ConnAssignerVirtualLinkType }, |
| 180 | - { "BR_PROXY_STATE", HISYSEVENT_INT32, ConnAssignerBrProxyState }, | 183 | + { "BR_PROXY_STATE", HISYSEVENT_INT32, ConnAssignerBrProxyState }, |
| 181 | { "BR_PROXY_IS_CLEAR", HISYSEVENT_INT32, ConnAssignerBrProxyIsClear }, | 184 | { "BR_PROXY_IS_CLEAR", HISYSEVENT_INT32, ConnAssignerBrProxyIsClear }, |
| 182 | { "BR_PROXY_IS_RETRY", HISYSEVENT_INT32, ConnAssignerBrProxyIsRetry }, | 185 | { "BR_PROXY_IS_RETRY", HISYSEVENT_INT32, ConnAssignerBrProxyIsRetry }, |
| 183 | - { "BR_PROXY_IS_ACL", HISYSEVENT_INT32, ConnAssignerBrProxyIsAcl }, | 186 | + { "BR_PROXY_IS_ACL", HISYSEVENT_INT32, ConnAssignerBrProxyIsAcl }, |
| 187 | + { "CONNECT_REASON", HISYSEVENT_INT32, ConnAssignerConnectReason }, | ||
| 188 | + { "SEND_CNT", HISYSEVENT_INT32, ConnAssignerSendCnt }, | ||
| 189 | + { "RECEIVE_CNT", HISYSEVENT_INT32, ConnAssignerReceiveCnt }, | ||
| 184 | // Modification Note: remember updating CONN_ASSIGNER_SIZE | 190 | // Modification Note: remember updating CONN_ASSIGNER_SIZE |
| 185 | }; | 191 | }; |
| 186 | 192 | ||
| @@ -40,6 +40,7 @@ typedef enum { | |||
| 40 | EVENT_SCENE_PAGING_PASSIVE_BROADCAST_RESPONSE = 13, | 40 | EVENT_SCENE_PAGING_PASSIVE_BROADCAST_RESPONSE = 13, |
| 41 | EVENT_SCENE_BR_PROXY = 14, | 41 | EVENT_SCENE_BR_PROXY = 14, |
| 42 | EVENT_SCENE_GENERAL_CONNECT = 15, | 42 | EVENT_SCENE_GENERAL_CONNECT = 15, |
| 43 | + EVENT_SCENE_FAR_FIELD = 16, | ||
| 43 | } ConnEventScene; | 44 | } ConnEventScene; |
| 44 | 45 | ||
| 45 | typedef enum { | 46 | typedef enum { |
| @@ -78,12 +79,29 @@ typedef enum { | |||
| 78 | EVENT_STAGE_BR_PROXY_STATE = 2110, | 79 | EVENT_STAGE_BR_PROXY_STATE = 2110, |
| 79 | EVENT_STAGE_BR_PROXY_RECONNECT = 2111, | 80 | EVENT_STAGE_BR_PROXY_RECONNECT = 2111, |
| 80 | EVENT_STAGE_BR_PROXY_SEND = 2112, | 81 | EVENT_STAGE_BR_PROXY_SEND = 2112, |
| 82 | + | ||
| 83 | + EVENT_STAGE_FAR_FIELD_START = 2200, // far field stage start[2201,2298] | ||
| 84 | + EVENT_STAGE_FAR_FIELD_END = 2299, // far field stage end[2201,2298] | ||
DfxEventExtra 结构体包含 char *func 和 char *hostPkg 裸指针,未定义所有权语义。若该结构体按值传递或浅拷贝,将导致双重释放、释放后使用或内存泄漏。 明确指针所有权:若为字符串字面量/静态字符串,使用 const char*;若需动态分配,提供深拷贝和释放函数,或使用固定长度字符数组替代。 ![]() ![]() | |||
| 81 | } ConnEventConnectStage; | 85 | } ConnEventConnectStage; |
| 82 | 86 | ||
| 83 | typedef enum { | 87 | typedef enum { |
新增结构体 DfxEventExtra 包含裸指针 char *func 和 char *hostPkg。如果该结构体实例被异步处理(如DFX事件上报)或按值复制,极易导致悬垂指针、Use-After-Free 或双重释放,引发严重崩溃。 避免在跨模块传递的结构体中使用裸指针。建议使用固定长度的字符数组(如 char func[MAX_LEN]),或明确要求调用方保证指针生命周期,并在结构体中增加深拷贝/释放机制。 ![]() ![]() | |||
| 84 | EVENT_STAGE_TCP_COMMON_ONE = 1, | 88 | EVENT_STAGE_TCP_COMMON_ONE = 1, |
| 85 | } ConnEventTcpCommonStage; | 89 | } ConnEventTcpCommonStage; |
| 86 | 90 | ||
| 91 | +typedef struct { | ||
| 92 | + char *func; | ||
| 93 | + int32_t line; | ||
| 94 | + int32_t bizScene; | ||
| 95 | + int32_t bizStage; | ||
| 96 | + int32_t stageRes; | ||
| 97 | + int32_t errorCode; | ||
| 98 | + char *hostPkg; | ||
| 99 | + int32_t connectReason; | ||
| 100 | + int32_t costTime; | ||
| 101 | + int32_t sendMsgCnt; | ||
| 102 | + int32_t receiveMsgCnt; | ||
| 103 | +} DfxEventExtra; | ||
| 104 | + | ||
| 87 | typedef struct { | 105 | typedef struct { |
| 88 | int32_t result; // STAGE_RES | 106 | int32_t result; // STAGE_RES |
| 89 | int32_t errcode; // ERROR_CODE | 107 | int32_t errcode; // ERROR_CODE |
| @@ -157,6 +175,9 @@ typedef struct { | |||
| 157 | int32_t brProxyIsClear; // BR_PROXY_IS_CLEAR | 175 | int32_t brProxyIsClear; // BR_PROXY_IS_CLEAR |
| 158 | int32_t brProxyIsRetry; // BR_PROXY_IS_RETRY | 176 | int32_t brProxyIsRetry; // BR_PROXY_IS_RETRY |
| 159 | int32_t brProxyIsAcl; // BR_PROXY_IS_ACL | 177 | int32_t brProxyIsAcl; // BR_PROXY_IS_ACL |
| 178 | + int32_t connectReason; // CONNECT_REASON | ||
| 179 | + int32_t sendCnt; // SEND_CNT | ||
在公共接口结构体 ConnEventExtra 末尾添加新字段会破坏ABI兼容性。如果存在新旧版本编译的模块(如动态库与主程序)相互调用,由于结构体大小不一致,会导致内存越界读写,引发崩溃或数据损坏。 如果此头文件用于跨模块/进程通信,不应直接修改现有结构体大小。应通过版本号机制、预留字段或新增的扩展结构体指针来传递额外数据,以确保向后兼容。 ![]() ![]() | |||
| 180 | + int32_t receiveCnt; // RECEIVE_CNT | ||
| 160 | } ConnEventExtra; | 181 | } ConnEventExtra; |
| 161 | 182 | ||
| 162 | typedef enum { | 183 | typedef enum { |
| @@ -556,7 +556,7 @@ enum SoftBusErrNo { | |||
| 556 | SOFTBUS_TRANS_DLOPEN_FAILED, | 556 | SOFTBUS_TRANS_DLOPEN_FAILED, |
| 557 | SOFTBUS_TRANS_DLSYM_FAILED, | 557 | SOFTBUS_TRANS_DLSYM_FAILED, |
| 558 | SOFTBUS_TRANS_DLCLOSE_FAILED, | 558 | SOFTBUS_TRANS_DLCLOSE_FAILED, |
| 559 | - SOFTBUS_TRANS_MATA_PLUGIN_IS_ENABLED, | 559 | + SOFTBUS_TRANS_META_PLUGIN_IS_ENABLE, |
| 560 | 560 | ||
| 561 | /* errno begin: -((203 << 21) | (3 << 16) | 0xFFFF) */ | 561 | /* errno begin: -((203 << 21) | (3 << 16) | 0xFFFF) */ |
| 562 | SOFTBUS_AUTH_ERR_BASE = SOFTBUS_ERRNO(AUTH_SUB_MODULE_CODE), | 562 | SOFTBUS_AUTH_ERR_BASE = SOFTBUS_ERRNO(AUTH_SUB_MODULE_CODE), |
| @@ -105,6 +105,9 @@ static int32_t MatchConnEventNameTypeExtraForAddMsg(const HiSysEventParam *param | |||
| 105 | MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.brProxyIsClear); | 105 | MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.brProxyIsClear); |
| 106 | MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.brProxyIsRetry); | 106 | MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.brProxyIsRetry); |
| 107 | MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.brProxyIsAcl); | 107 | MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.brProxyIsAcl); |
| 108 | + MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.connectReason); | ||
新增3次对 params 数组的访问(connectReason、sendCnt、receiveCnt),但未见对 params 数组大小的边界检查。若调用方传入的 params 数组仍按旧的参数数量分配,将导致数组越界读取(buffer over-read),属于内存安全问题。 确认所有调用方传入的 params 数组容量已同步更新以容纳新增的3个参数;或在 MatchConnEventNameTypeExtraInt32Param 中增加对 index 相对于 paramCount 的边界校验。 ![]() ![]() | |||
| 109 | + MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.sendCnt); | ||
| 110 | + MatchConnEventNameTypeExtraInt32Param(params, ++index, extra.receiveCnt); | ||
| 108 | return ++index; | 111 | return ++index; |
| 109 | } | 112 | } |
| 110 | 113 | ||
| @@ -98,6 +98,9 @@ static ConnEventExtra g_validExtra = { | |||
| 98 | .brProxyIsClear = 1, | 98 | .brProxyIsClear = 1, |
| 99 | .brProxyIsRetry = 1, | 99 | .brProxyIsRetry = 1, |
| 100 | .brProxyIsAcl = 1, | 100 | .brProxyIsAcl = 1, |
| 101 | + .connectReason = 1, | ||
| 102 | + .sendCnt = 1, | ||
| 103 | + .receiveCnt = 1, | ||
| 101 | }; | 104 | }; |
| 102 | 105 | ||
| 103 | /* | 106 | /* |
| @@ -219,7 +222,7 @@ static ConnEventExtra g_invalidExtra = { | |||
| 219 | HWTEST_F(ConnEventTest, ConnEventTest003, TestSize.Level0) | 222 | HWTEST_F(ConnEventTest, ConnEventTest003, TestSize.Level0) |
| 220 | { | 223 | { |
| 221 | constexpr int32_t TWO_VALID_EXTRA_SIZE = 2; // result, errcode is valid | 224 | constexpr int32_t TWO_VALID_EXTRA_SIZE = 2; // result, errcode is valid |
| 222 | - constexpr int32_t VALID_EXTRA_SIZE = 34; | 225 | + constexpr int32_t VALID_EXTRA_SIZE = 37; |
| 223 | 226 | ||
| 224 | HiSysEventMock mock; | 227 | HiSysEventMock mock; |
| 225 | EXPECT_CALL(mock, | 228 | EXPECT_CALL(mock, |
| @@ -240,7 +243,7 @@ HWTEST_F(ConnEventTest, ConnEventTest004, TestSize.Level0) | |||
| 240 | { | 243 | { |
| 241 | ConnEventExtra emptyExtra = { 0 }; | 244 | ConnEventExtra emptyExtra = { 0 }; |
| 242 | constexpr int32_t TWO_VALID_EXTRA_SIZE = 2; // result, errcode is valid | 245 | constexpr int32_t TWO_VALID_EXTRA_SIZE = 2; // result, errcode is valid |
| 243 | - constexpr int32_t VALID_EXTRA_SIZE = 34; | 246 | + constexpr int32_t VALID_EXTRA_SIZE = 37; |
| 244 | 247 | ||
| 245 | HiSysEventMock mock; | 248 | HiSysEventMock mock; |
| 246 | EXPECT_CALL(mock, | 249 | EXPECT_CALL(mock, |


AnonymizeWrapper() 被调用在已经通过 Anonymize() 匿名化处理过的 BrMacTmp 和 uuidTmp 上。如果 AnonymizeWrapper 内部分配内存,则该内存永远不会被释放(仅 AnonymizeFree 了原始的 BrMacTmp/uuidTmp),导致内存泄漏。如果 AnonymizeWrapper 使用静态缓冲区,则两次调用会互相覆盖,导致日志中 brMac 和 uuid 显示相同的值。
移除冗余的 Anonymize/AnonymizeFree 调用,直接对原始 brMac 和 uuid 使用 AnonymizeWrapper;或者移除 AnonymizeWrapper 包装,直接使用已匿名化的 BrMacTmp/uuidTmp。