• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 
16 #include "inspector_utils.h"
17 
18 #include "jsvm_dfx.h"
19 #include "unicode/unistr.h"
20 
21 #if HAVE_OPENSSL
22 #include "openssl/opensslv.h"
23 #endif
24 
25 #if OPENSSL_VERSION_MAJOR >= 3
26 #include "openssl/provider.h"
27 #endif
28 
29 #include <openssl/err.h>
30 #include <openssl/rand.h>
31 
32 namespace jsvm {
33 namespace inspector {
34 namespace {
Utf8ToUtf16(const char * data,size_t len)35 inline icu::UnicodeString Utf8ToUtf16(const char* data, size_t len)
36 {
37     icu::UnicodeString utf16Str = icu::UnicodeString::fromUTF8(icu::StringPiece(data, len));
38 
39     return utf16Str;
40 }
41 
Utf16ToUtf8(const char16_t * data,size_t length)42 inline std::string Utf16ToUtf8(const char16_t* data, size_t length)
43 {
44     icu::UnicodeString unicodeStr(data, length);
45     std::string utf8Str;
46     unicodeStr.toUTF8String(utf8Str);
47 
48     return utf8Str;
49 }
50 } // namespace
51 
Utf8ToStringView(const std::string_view message)52 std::unique_ptr<v8_inspector::StringBuffer> Utf8ToStringView(const std::string_view message)
53 {
54     icu::UnicodeString utf16Str = Utf8ToUtf16(message.data(), message.length());
55     size_t utf16Len = utf16Str.length();
56 
57     v8_inspector::StringView view(reinterpret_cast<const uint16_t*>(utf16Str.getBuffer()), utf16Len);
58     return v8_inspector::StringBuffer::create(view);
59 }
60 
StringViewToUtf8(v8_inspector::StringView view)61 std::string StringViewToUtf8(v8_inspector::StringView view)
62 {
63     if (view.length() == 0) {
64         return "";
65     }
66     if (view.is8Bit()) {
67         return std::string(reinterpret_cast<const char*>(view.characters8()), view.length());
68     }
69     const char16_t* source = reinterpret_cast<const char16_t*>(view.characters16());
70 
71     return Utf16ToUtf8(source, view.length());
72 }
73 
74 static constexpr char BASE64_CHAR_SET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
75 
76 // clang-format off
Base64Encode(const char * inputString,size_t slen,char * outputBuffer,size_t dlen)77 size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, size_t dlen)
78 {
79     // 1: caluate encode size and check
80     size_t strLen = slen;
81     size_t encodedStrLen = Base64EncodeSize(slen);
82 
83     CHECK_GE(dlen, encodedStrLen);
84 
85     // 2: the index do not exceed the range of outputBuffer and form a complete four-character block
86     for (size_t i = 0, j = 0; j < strLen - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) {
87         // convert three 8bit into four 6bit; then add two 0 bit in each 6 bit
88         // former 00 + first 6 bits of the first char
89         outputBuffer[i] = BASE64_CHAR_SET[(static_cast<unsigned int>(inputString[j]) & 0xff) >> ByteOffset::BIT_2];
90         // 00 + the last 2 bits of the first char + the first 4 bits of the second char
91         outputBuffer[i + ByteOffset::BYTE_1] =
92             BASE64_CHAR_SET[(static_cast<unsigned int>(inputString[j]) & 0x03) << ByteOffset::BIT_4 |
93                             (static_cast<unsigned int>(inputString[j + ByteOffset::BYTE_1]) & 0xf0) >>
94                                 ByteOffset::BIT_4];
95         // 00 + last 4 bits of the second char + the first 2 bits of the third char
96         outputBuffer[i + ByteOffset::BYTE_2] =
97             BASE64_CHAR_SET[(static_cast<unsigned int>(inputString[j + ByteOffset::BYTE_1]) & 0x0f) <<
98                                 ByteOffset::BIT_2 |
99                             (static_cast<unsigned int>(inputString[j + ByteOffset::BYTE_2]) & 0xc0) >>
100                                 ByteOffset::BIT_6];
101         // 00 + the last 6 bits of the third char
102         outputBuffer[i + ByteOffset::BYTE_3] =
103             BASE64_CHAR_SET[static_cast<unsigned int>(inputString[j + ByteOffset::BYTE_2]) & 0x3f];
104     }
105     switch (strLen % TO_TRANSFORM_CHAR_NUM) {
106         // the original string is less than three bytes, and the missing place is filled with '=' to patch four bytes
107         case ByteSize::SIZE_1_BYTES:
108             // 1,2: the original character is one, and two characters are missing after conversion
109             outputBuffer[encodedStrLen - ByteOffset::BYTE_4] =
110                 BASE64_CHAR_SET[(static_cast<unsigned int>(inputString[strLen - ByteOffset::BYTE_1]) & 0xff) >>
111                                 ByteOffset::BIT_2];
112             outputBuffer[encodedStrLen - ByteOffset::BYTE_3] =
113                 BASE64_CHAR_SET[(static_cast<unsigned int>(inputString[strLen - ByteOffset::BYTE_1]) & 0x03) <<
114                                 ByteOffset::BIT_4];
115             outputBuffer[encodedStrLen - ByteOffset::BYTE_2] = '=';
116             outputBuffer[encodedStrLen - ByteOffset::BYTE_1] = '=';
117             break;
118         case ByteSize::SIZE_2_BYTES:
119             // 1: the original character is two, and a character are missing after conversion
120             outputBuffer[encodedStrLen - ByteOffset::BYTE_4] =
121                 BASE64_CHAR_SET[(static_cast<unsigned int>(inputString[strLen - ByteOffset::BYTE_2]) & 0xff) >>
122                                 ByteOffset::BIT_2];
123             outputBuffer[encodedStrLen - ByteOffset::BYTE_3] =
124                 BASE64_CHAR_SET[(static_cast<unsigned int>(inputString[strLen - ByteOffset::BYTE_2]) & 0x03) <<
125                                 ByteOffset::BIT_4 |
126                                 (static_cast<unsigned int>(inputString[strLen - ByteOffset::BYTE_1]) & 0xf0) >>
127                                     ByteOffset::BIT_4];
128             outputBuffer[encodedStrLen - ByteOffset::BYTE_2] =
129                 BASE64_CHAR_SET[(static_cast<unsigned int>(inputString[strLen - ByteOffset::BYTE_1]) & 0x0f) <<
130                                 ByteOffset::BIT_2];
131             outputBuffer[encodedStrLen - ByteOffset::BYTE_1] = '=';
132             break;
133         default:
134             break;
135     }
136 
137     return encodedStrLen;
138 }
139 // clang-format on
140 
GetHumanReadableProcessName()141 std::string GetHumanReadableProcessName()
142 {
143     return "JSVM[" + std::to_string(platform::OS::GetPid()) + "]";
144 }
145 
CSPRNG(void * buffer,size_t length)146 MUST_USE_RESULT bool CSPRNG(void* buffer, size_t length)
147 {
148     unsigned char* buf = static_cast<unsigned char*>(buffer);
149     do {
150         if (RAND_status() == 1) {
151 #if OPENSSL_VERSION_MAJOR >= 3
152             if (RAND_bytes_ex(nullptr, buf, length, 0) == 1) {
153                 return true;
154             }
155 #else
156             while (length > INT_MAX && RAND_bytes(buf, INT_MAX) == 1) {
157                 buf += INT_MAX;
158                 length -= INT_MAX;
159             }
160             if (length <= INT_MAX && RAND_bytes(buf, static_cast<int>(length)) == 1) {
161                 return true;
162             }
163 #endif
164         }
165 #if OPENSSL_VERSION_MAJOR >= 3
166         const auto code = ERR_peek_last_error();
167         // A misconfigured OpenSSL 3 installation may report 1 from RAND_poll()
168         // and RAND_status() but fail in RAND_bytes() if it cannot look up
169         // a matching algorithm for the CSPRNG.
170         if (ERR_GET_LIB(code) == ERR_LIB_RAND) {
171             const auto reason = ERR_GET_REASON(code);
172             if (reason == RAND_R_ERROR_INSTANTIATING_DRBG || reason == RAND_R_UNABLE_TO_FETCH_DRBG ||
173                 reason == RAND_R_UNABLE_TO_CREATE_DRBG) {
174                 return false;
175             }
176         }
177 #endif
178     } while (RAND_poll() == 1);
179 
180     return false;
181 }
182 
CheckedUvLoopClose(uv_loop_t * loop)183 void CheckedUvLoopClose(uv_loop_t* loop)
184 {
185     if (uv_loop_close(loop) == 0) {
186         return;
187     }
188 
189     // Finally, abort.
190     UNREACHABLE("uv_loop_close() while having open handles");
191 }
192 
193 using v8::Isolate;
194 using v8::Local;
195 using v8::String;
196 using v8::Value;
197 
TwoByteValue(Isolate * isolate,Local<Value> value)198 TwoByteValue::TwoByteValue(Isolate* isolate, Local<Value> value)
199 {
200     if (value.IsEmpty()) {
201         return;
202     }
203 
204     Local<String> string;
205     if (!value->ToString(isolate->GetCurrentContext()).ToLocal(&string)) {
206         return;
207     }
208 
209     // Allocate enough space to include the null terminator
210     const size_t storage = string->Length() + 1;
211     AllocateSufficientStorage(storage);
212 
213     const int flags = String::NO_NULL_TERMINATION;
214     const int length = string->Write(isolate, Out(), 0, storage, flags);
215     SetLengthAndZeroTerminate(length);
216 }
217 } // namespace inspector
218 } // namespace jsvm