1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifdef USE_NATIVE_TOKEN_KLOG
16 #include "accesstoken_klog.h"
17 #else
18 #include "accesstoken_common_log.h"
19 #endif
20
21 #include <cstdlib>
22 #include <cstdio>
23 #include <cstdarg>
24 #include <cstdint>
25 #include <cstring>
26 #include <string>
27 #include "securec.h"
28
29 static constexpr uint32_t MAX_ERROR_MESSAGE_LEN = 4096;
30 static __thread uint32_t g_msgLen = 0;
31 static __thread char g_errMsg[MAX_ERROR_MESSAGE_LEN + 1];
32
33 #ifdef USE_NATIVE_TOKEN_KLOG
34 #define ACCESSTOKEN_COMMON_LOGE(domain, tag, fmt, ...) \
35 ((void)LOGE(fmt, ##__VA_ARGS__))
36 #else
37 #define ACCESSTOKEN_COMMON_LOGE(domain, tag, fmt, ...) \
38 ((void)LOGE(domain, tag, fmt, ##__VA_ARGS__))
39 #endif
40
GetThreadErrorMsgLen(void)41 uint32_t GetThreadErrorMsgLen(void)
42 {
43 return g_msgLen;
44 }
45
GetThreadErrorMsg(void)46 const char* GetThreadErrorMsg(void)
47 {
48 return g_errMsg;
49 }
50
ClearThreadErrorMsg(void)51 void ClearThreadErrorMsg(void)
52 {
53 (void)memset_s(g_errMsg, MAX_ERROR_MESSAGE_LEN + 1, 0, MAX_ERROR_MESSAGE_LEN + 1);
54 g_msgLen = 0;
55 }
56
AppendThreadErrMsg(unsigned int domain,const char * tag,const uint8_t * buff,uint32_t buffLen)57 void AppendThreadErrMsg(unsigned int domain, const char* tag,
58 const uint8_t* buff, uint32_t buffLen)
59 {
60 if (g_msgLen + buffLen >= MAX_ERROR_MESSAGE_LEN) {
61 ACCESSTOKEN_COMMON_LOGE(domain, tag, "Buff will overflow!"
62 "g_msgLen = %" LOG_PUBLIC "u, buffLen = %" LOG_PUBLIC "u", g_msgLen, buffLen);
63 return;
64 }
65 if (memcpy_s(g_errMsg + g_msgLen, MAX_ERROR_MESSAGE_LEN - g_msgLen, buff, buffLen) != EOK) {
66 ACCESSTOKEN_COMMON_LOGE(domain, tag, "Failed to memcpy_s!"
67 "g_msgLen = %" LOG_PUBLIC "u, buffLen = %" LOG_PUBLIC "u", g_msgLen, buffLen);
68 return;
69 }
70 g_msgLen += buffLen;
71 }
72
ReplaceSubstring(unsigned int domain,const char * tag,const char * format,char result[MAX_ERROR_MESSAGE_LEN])73 static bool ReplaceSubstring(unsigned int domain, const char* tag,
74 const char* format, char result[MAX_ERROR_MESSAGE_LEN])
75 {
76 std::string formatString(format);
77 #ifndef USE_NATIVE_TOKEN_KLOG
78 std::string::size_type pos;
79 while ((pos = formatString.find(LOG_PUBLIC)) != std::string::npos) {
80 formatString.replace(pos, strlen(LOG_PUBLIC), "");
81 }
82 #endif
83 if (memcpy_s(result, MAX_ERROR_MESSAGE_LEN, formatString.c_str(), formatString.size()) != EOK) {
84 return false;
85 }
86 return true;
87 }
88
AddEventMessage(unsigned int domain,const char * tag,const char * format,...)89 void AddEventMessage(unsigned int domain, const char* tag,
90 const char* format, ...)
91 {
92 va_list ap;
93
94 if (g_msgLen == 0) {
95 char newFormat[MAX_ERROR_MESSAGE_LEN] = {0};
96 if (!ReplaceSubstring(domain, tag, format, newFormat)) {
97 ACCESSTOKEN_COMMON_LOGE(domain, tag, "Skip to add errMsg");
98 return;
99 }
100 va_start(ap, format);
101 char buff[MAX_ERROR_MESSAGE_LEN] = {0};
102 int32_t buffLen = vsnprintf_s(buff, MAX_ERROR_MESSAGE_LEN, MAX_ERROR_MESSAGE_LEN - 1, newFormat, ap);
103 va_end(ap);
104 if (buffLen < 0) {
105 ACCESSTOKEN_COMMON_LOGE(domain, tag,
106 "Failed to vsnprintf_s! Ret: %" LOG_PUBLIC "d, newFormat:[%" LOG_PUBLIC "s]", buffLen, newFormat);
107 return;
108 }
109 if (g_msgLen + static_cast<uint32_t>(buffLen) >= MAX_ERROR_MESSAGE_LEN) {
110 ACCESSTOKEN_COMMON_LOGE(domain, tag, "ErrMsg is almost full!");
111 return;
112 }
113
114 if (memcpy_s(g_errMsg + g_msgLen, MAX_ERROR_MESSAGE_LEN, buff, buffLen) != EOK) {
115 ACCESSTOKEN_COMMON_LOGE(domain, tag, "Failed to copy errMsg buff!");
116 return;
117 }
118 g_msgLen += static_cast<uint32_t>(buffLen);
119 } else {
120 va_start(ap, format);
121 char* funName = va_arg(ap, char*);
122 uint32_t lineNo = va_arg(ap, uint32_t);
123 va_end(ap);
124
125 if (funName == nullptr) {
126 ACCESSTOKEN_COMMON_LOGE(domain, tag, "Get funName fail!");
127 return;
128 }
129 int32_t offset = sprintf_s(g_errMsg + g_msgLen, MAX_ERROR_MESSAGE_LEN - g_msgLen, " <%s[%u]",
130 funName, lineNo);
131 if (offset <= 0) {
132 ACCESSTOKEN_COMMON_LOGE(domain, tag, "Failed to append call chain! Offset: [%" LOG_PUBLIC "d]", offset);
133 return;
134 }
135 g_msgLen += static_cast<uint32_t>(offset);
136 }
137 }
138