From 12ae953df2843ddda9e3c3410821a99851da6440 Mon Sep 17 00:00:00 2001 From: liuweili Date: Sat, 11 Jan 2025 15:07:16 +0800 Subject: [PATCH 1/3] add inspector utils Signed-off-by: liuweili --- src/inspector/inspector_utils.cpp | 207 +++++++++++++++++++ src/inspector/inspector_utils.h | 323 ++++++++++++++++++++++++++++++ 2 files changed, 530 insertions(+) create mode 100644 src/inspector/inspector_utils.cpp create mode 100644 src/inspector/inspector_utils.h diff --git a/src/inspector/inspector_utils.cpp b/src/inspector/inspector_utils.cpp new file mode 100644 index 0000000..3fee95d --- /dev/null +++ b/src/inspector/inspector_utils.cpp @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "inspector_utils.h" + +#include "jsvm_dfx.h" +#include "unicode/unistr.h" + +#if HAVE_OPENSSL +#include "openssl/opensslv.h" +#endif + +#if OPENSSL_VERSION_MAJOR >= 3 +#include "openssl/provider.h" +#endif + +#include +#include + +namespace jsvm { +namespace inspector { +namespace { +inline icu::UnicodeString Utf8ToUtf16(const char* data, size_t len) +{ + icu::UnicodeString utf16Str = icu::UnicodeString::fromUTF8(icu::StringPiece(data, len)); + + return utf16Str; +} + +inline std::string Utf16toUtf8(const char16_t* data, size_t length) +{ + icu::UnicodeString unicodeStr(data, length); + std::string utf8Str; + unicodeStr.toUTF8String(utf8Str); + + return utf8Str; +} +} // namespace + +std::unique_ptr Utf8ToStringView(const std::string_view message) +{ + icu::UnicodeString utf16Str = Utf8ToUtf16(message.data(), message.length()); + size_t utf16Len = utf16Str.length(); + + v8_inspector::StringView view(reinterpret_cast(utf16Str.getBuffer()), utf16Len); + return v8_inspector::StringBuffer::create(view); +} + +std::string StringViewToUtf8(v8_inspector::StringView view) +{ + if (view.length() == 0) { + return ""; + } + if (view.is8Bit()) { + return std::string(reinterpret_cast(view.characters8()), view.length()); + } + const char16_t* source = reinterpret_cast(view.characters16()); + + return Utf16toUtf8(source, view.length()); +} + +constexpr size_t TO_TRANSFORM_CHAR_NUM = 3; +constexpr size_t TRANSFORMED_CHAR_NUM = 4; + +static constexpr char base64CharSet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, size_t dlen) +{ + // 1: caluate encode size and check + size_t strLen = slen; + size_t encodedStrLen = Base64EncodeSize(slen); + + CHECK_GE(dlen, encodedStrLen); + + // 2: the index do not exceed the range of outputBuffer and form a complete four-character block + for (size_t i = 0, j = 0; j < strLen - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) { + // convert three 8bit into four 6bit; then add two 0 bit in each 6 bit + // former 00 + first 6 bits of the first char + outputBuffer[i] = base64CharSet[(static_cast(inputString[j]) & 0xff) >> 2]; + // 00 + the last 2 bits of the first char + the first 4 bits of the second char + outputBuffer[i + 1] = base64CharSet[(static_cast(inputString[j]) & 0x03) << 4 | + (static_cast(inputString[j + 1]) & 0xf0) >> 4]; + // 00 + last 4 bits of the second char + the first 2 bits of the third char + outputBuffer[i + 2] = base64CharSet[(static_cast(inputString[j + 1]) & 0x0f) << 2 | + (static_cast(inputString[j + 2]) & 0xc0) >> 6]; + // 00 + the last 6 bits of the third char + outputBuffer[i + 3] = base64CharSet[static_cast(inputString[j + 2]) & 0x3f]; + } + switch (strLen % TO_TRANSFORM_CHAR_NUM) { + // the original string is less than three bytes, and the missing place is filled with '=' to patch four bytes + case 1: + // 1,2: the original character is one, and two characters are missing after conversion + outputBuffer[encodedStrLen - 4] = + base64CharSet[(static_cast(inputString[strLen - 1]) & 0xff) >> 2]; + outputBuffer[encodedStrLen - 3] = + base64CharSet[(static_cast(inputString[strLen - 1]) & 0x03) << 4]; + outputBuffer[encodedStrLen - 2] = '='; + outputBuffer[encodedStrLen - 1] = '='; + break; + case 2: + // 1: the original character is two, and a character are missing after conversion + outputBuffer[encodedStrLen - 4] = + base64CharSet[(static_cast(inputString[strLen - 2]) & 0xff) >> 2]; + outputBuffer[encodedStrLen - 3] = + base64CharSet[(static_cast(inputString[strLen - 2]) & 0x03) << 4 | + (static_cast(inputString[strLen - 1]) & 0xf0) >> 4]; + outputBuffer[encodedStrLen - 2] = + base64CharSet[(static_cast(inputString[strLen - 1]) & 0x0f) << 2]; + outputBuffer[encodedStrLen - 1] = '='; + break; + default: + break; + } + + return encodedStrLen; +} + +std::string GetHumanReadableProcessName() +{ + return "JSVM[" + std::to_string(platform::OS::GetPid()) + "]"; +} + +MUST_USE_RESULT bool CSPRNG(void* buffer, size_t length) +{ + unsigned char* buf = static_cast(buffer); + do { + if (RAND_status() == 1) { +#if OPENSSL_VERSION_MAJOR >= 3 + if (RAND_bytes_ex(nullptr, buf, length, 0) == 1) { + return true; + } +#else + while (length > INT_MAX && RAND_bytes(buf, INT_MAX) == 1) { + buf += INT_MAX; + length -= INT_MAX; + } + if (length <= INT_MAX && RAND_bytes(buf, static_cast(length)) == 1) { + return true; + } +#endif + } +#if OPENSSL_VERSION_MAJOR >= 3 + const auto code = ERR_peek_last_error(); + // A misconfigured OpenSSL 3 installation may report 1 from RAND_poll() + // and RAND_status() but fail in RAND_bytes() if it cannot look up + // a matching algorithm for the CSPRNG. + if (ERR_GET_LIB(code) == ERR_LIB_RAND) { + const auto reason = ERR_GET_REASON(code); + if (reason == RAND_R_ERROR_INSTANTIATING_DRBG || reason == RAND_R_UNABLE_TO_FETCH_DRBG || + reason == RAND_R_UNABLE_TO_CREATE_DRBG) { + return false; + } + } +#endif + } while (RAND_poll() == 1); + + return false; +} + +void CheckedUvLoopClose(uv_loop_t* loop) +{ + if (uv_loop_close(loop) == 0) { + return; + } + + // Finally, abort. + UNREACHABLE("uv_loop_close() while having open handles"); +} + +using v8::Isolate; +using v8::Local; +using v8::String; +using v8::Value; + +TwoByteValue::TwoByteValue(Isolate* isolate, Local value) +{ + if (value.IsEmpty()) { + return; + } + + Local string; + if (!value->ToString(isolate->GetCurrentContext()).ToLocal(&string)) { + return; + } + + // Allocate enough space to include the null terminator + const size_t storage = string->Length() + 1; + AllocateSufficientStorage(storage); + + const int flags = String::NO_NULL_TERMINATION; + const int length = string->Write(isolate, out(), 0, storage, flags); + SetLengthAndZeroTerminate(length); +} +} // namespace inspector +} // namespace jsvm \ No newline at end of file diff --git a/src/inspector/inspector_utils.h b/src/inspector/inspector_utils.h new file mode 100644 index 0000000..c2c5527 --- /dev/null +++ b/src/inspector/inspector_utils.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INSPECTOR_UTILS_H +#define INSPECTOR_UTILS_H +#include +#include +#include + +#include "jsvm_dfx.h" +#include "jsvm_util.h" +#include "uv.h" +#include "v8-inspector.h" + +#ifdef __GNUC__ +#define MUST_USE_RESULT __attribute__((warn_unused_result)) +#else +#define MUST_USE_RESULT +#endif + +namespace jsvm { +namespace inspector { +// // The helper is for doing safe downcasts from base types to derived types. +template +class ContainerOfHelper { +public: + inline ContainerOfHelper(Inner Outer::*field, Inner* pointer); + template + inline operator TypeName*() const; + +private: + Outer* const pointer; +}; + +inline char ToLower(char c) +{ + return std::tolower(c, std::locale::classic()); +} + +inline bool StringEqualNoCase(const char* a, const char* b) +{ + while (ToLower(*a) == ToLower(*b++)) { + if (*a++ == '\0') { + return true; + } + } + return false; +} + +inline bool StringEqualNoCaseN(const char* a, const char* b, size_t length) +{ + for (size_t i = 0; i < length; i++) { + if (ToLower(a[i]) != ToLower(b[i])) { + return false; + } + if (a[i] == '\0') { + return true; + } + } + return true; +} + +// Use this when a variable or parameter is unused in order to explicitly +// silence a compiler warning about that. +template +inline void USE(T&&) +{} + +// Used to be a macro, hence the uppercase name. +template +inline v8::Local FIXED_ONE_BYTE_STRING(v8::Isolate* isolate, const char (&data)[N]) +{ + return OneByteString(isolate, data, N - 1); +} + +template +inline v8::Local FIXED_ONE_BYTE_STRING(v8::Isolate* isolate, const std::array& arr) +{ + return OneByteString(isolate, arr.data(), N - 1); +} + +template +struct FunctionDeleter { + void operator()(T* pointer) const + { + function(pointer); + } + typedef std::unique_ptr Pointer; +}; + +template +using DeleteFnPtr = typename FunctionDeleter::Pointer; + +template +constexpr uintptr_t OffsetOf(Inner Outer::*field) +{ + return reinterpret_cast(&(static_cast(nullptr)->*field)); +} + +template +ContainerOfHelper::ContainerOfHelper(Inner Outer::*field, Inner* pointer) + : pointer(reinterpret_cast(reinterpret_cast(pointer) - OffsetOf(field))) +{} + +template +template +ContainerOfHelper::operator TypeName*() const +{ + return static_cast(pointer); +} + +// Calculate the address of the outer (i.e. embedding) struct from +// the interior pointer to a data member. +template +constexpr ContainerOfHelper ContainerOf(Inner Outer::*field, Inner* pointer) +{ + return ContainerOfHelper(field, pointer); +} + +// util.h +// Allocates an array of member type T. For up to kStackStorageSize items, +// the stack is used, otherwise malloc(). +template +class MaybeStackBuffer { +public: + const T* out() const + { + return buf; + } + + T* out() + { + return buf; + } + + // operator* for compatibility with `v8::String::(Utf8)Value` + T* operator*() + { + return buf; + } + + const T* operator*() const + { + return buf; + } + + T& operator[](size_t index) + { + CHECK_LT(index, GetLength()); + return buf[index]; + } + + const T& operator[](size_t index) const + { + CHECK_LT(index, GetLength()); + return buf[index]; + } + + size_t GetLength() const + { + return length; + } + + // Current maximum capacity of the buffer with which SetLength() can be used + // without first calling AllocateSufficientStorage(). + size_t GetCapacity() const + { + return capacity; + } + + // Make sure enough space for `storage` entries is available. + // This method can be called multiple times throughout the lifetime of the + // buffer, but once this has been called Invalidate() cannot be used. + // Content of the buffer in the range [0, GetLength()) is preserved. + void AllocateSufficientStorage(size_t storage); + + void SetLength(size_t lengthParam) + { + // GetCapacity() returns how much memory is actually available. + CHECK_LE(lengthParam, GetCapacity()); + length = lengthParam; + } + + void SetLengthAndZeroTerminate(size_t len) + { + // GetCapacity() returns how much memory is actually available. + CHECK_LE(len + 1, GetCapacity()); + SetLength(len); + + // T() is 0 for integer types, nullptr for pointers, etc. + buf[len] = T(); + } + + // Make dereferencing this object return nullptr. + // This method can be called multiple times throughout the lifetime of the + // buffer, but once this has been called AllocateSufficientStorage() cannot + // be used. + void Invalidate() + { + CHECK(!IsAllocated()); + capacity = 0; + length = 0; + buf = nullptr; + } + + // If the buffer is stored in the heap rather than on the stack. + bool IsAllocated() const + { + return !IsInvalidated() && buf != bufSt; + } + + // If Invalidate() has been called. + bool IsInvalidated() const + { + return buf == nullptr; + } + + // Release ownership of the malloc'd buffer. + // Note: This does not free the buffer. + void Release() + { + CHECK(IsAllocated()); + buf = bufSt; + length = 0; + capacity = jsvm::ArraySize(bufSt); + } + + MaybeStackBuffer() : length(0), capacity(jsvm::ArraySize(bufSt)), buf(bufSt) + { + // Default to a zero-length, null-terminated buffer. + buf[0] = T(); + } + + explicit MaybeStackBuffer(size_t storage) : MaybeStackBuffer() + { + AllocateSufficientStorage(storage); + } + + ~MaybeStackBuffer() + { + if (IsAllocated()) { + free(buf); + } + } + + inline std::basic_string ToString() const + { + return { out(), GetLength() }; + } + inline std::basic_string_view ToStringView() const + { + return { out(), GetLength() }; + } + +private: + size_t length; + // capacity of the malloc'ed buf + size_t capacity; + T* buf; + T bufSt[kStackStorageSize]; +}; + +class TwoByteValue : public MaybeStackBuffer { +public: + explicit TwoByteValue(v8::Isolate* isolate, v8::Local value); +}; + +// TODO: replace realloc with Realloc +template +void MaybeStackBuffer::AllocateSufficientStorage(size_t storage) +{ + CHECK(!IsInvalidated()); + if (storage > GetCapacity()) { + bool wasAllocated = IsAllocated(); + T* allocatedPtr = wasAllocated ? buf : nullptr; + buf = reinterpret_cast(realloc(allocatedPtr, storage)); + capacity = storage; + if (!wasAllocated && length > 0) { + memcpy(buf, bufSt, length * sizeof(buf[0])); + } + } + + length = storage; +} + +// Convertion between v8_inspector::StringView and std::string +std::string StringViewToUtf8(v8_inspector::StringView view); +std::unique_ptr Utf8ToStringView(const std::string_view message); + +// Encode base64 +inline constexpr size_t Base64EncodeSize(size_t size) +{ + return ((size + 2) / 3 * 4); +} + +// Be careful: If dlen is less than expected encode size, it will crash. +size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, size_t dlen); + +std::string GetHumanReadableProcessName(); + +// Either succeeds with exactly |length| bytes of cryptographically +// strong pseudo-random data, or fails. This function may block. +// Don't assume anything about the contents of |buffer| on error. +// As a special case, |length == 0| can be used to check if the CSPRNG +// is properly seeded without consuming entropy. +MUST_USE_RESULT bool CSPRNG(void* buffer, size_t length); + +void CheckedUvLoopClose(uv_loop_t* loop); +} // namespace inspector +} // namespace jsvm +#endif \ No newline at end of file -- Gitee From 232c79e0261e5d4674b12e3ad851640c753d81bf Mon Sep 17 00:00:00 2001 From: liuweili Date: Sat, 11 Jan 2025 15:35:44 +0800 Subject: [PATCH 2/3] fix code check Signed-off-by: liuweili --- src/inspector/inspector_utils.cpp | 22 +++++++++++----------- src/inspector/inspector_utils.h | 30 ++++++++++-------------------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/inspector/inspector_utils.cpp b/src/inspector/inspector_utils.cpp index 3fee95d..bc2cc77 100644 --- a/src/inspector/inspector_utils.cpp +++ b/src/inspector/inspector_utils.cpp @@ -74,7 +74,7 @@ std::string StringViewToUtf8(v8_inspector::StringView view) constexpr size_t TO_TRANSFORM_CHAR_NUM = 3; constexpr size_t TRANSFORMED_CHAR_NUM = 4; -static constexpr char base64CharSet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static constexpr char BASE64_CHAR_SET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, size_t dlen) { @@ -88,36 +88,36 @@ size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, si for (size_t i = 0, j = 0; j < strLen - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) { // convert three 8bit into four 6bit; then add two 0 bit in each 6 bit // former 00 + first 6 bits of the first char - outputBuffer[i] = base64CharSet[(static_cast(inputString[j]) & 0xff) >> 2]; + outputBuffer[i] = BASE64_CHAR_SET[(static_cast(inputString[j]) & 0xff) >> 2]; // 00 + the last 2 bits of the first char + the first 4 bits of the second char - outputBuffer[i + 1] = base64CharSet[(static_cast(inputString[j]) & 0x03) << 4 | + outputBuffer[i + 1] = BASE64_CHAR_SET[(static_cast(inputString[j]) & 0x03) << 4 | (static_cast(inputString[j + 1]) & 0xf0) >> 4]; // 00 + last 4 bits of the second char + the first 2 bits of the third char - outputBuffer[i + 2] = base64CharSet[(static_cast(inputString[j + 1]) & 0x0f) << 2 | + outputBuffer[i + 2] = BASE64_CHAR_SET[(static_cast(inputString[j + 1]) & 0x0f) << 2 | (static_cast(inputString[j + 2]) & 0xc0) >> 6]; // 00 + the last 6 bits of the third char - outputBuffer[i + 3] = base64CharSet[static_cast(inputString[j + 2]) & 0x3f]; + outputBuffer[i + 3] = BASE64_CHAR_SET[static_cast(inputString[j + 2]) & 0x3f]; } switch (strLen % TO_TRANSFORM_CHAR_NUM) { // the original string is less than three bytes, and the missing place is filled with '=' to patch four bytes case 1: // 1,2: the original character is one, and two characters are missing after conversion outputBuffer[encodedStrLen - 4] = - base64CharSet[(static_cast(inputString[strLen - 1]) & 0xff) >> 2]; + BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0xff) >> 2]; outputBuffer[encodedStrLen - 3] = - base64CharSet[(static_cast(inputString[strLen - 1]) & 0x03) << 4]; + BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0x03) << 4]; outputBuffer[encodedStrLen - 2] = '='; outputBuffer[encodedStrLen - 1] = '='; break; case 2: // 1: the original character is two, and a character are missing after conversion outputBuffer[encodedStrLen - 4] = - base64CharSet[(static_cast(inputString[strLen - 2]) & 0xff) >> 2]; + BASE64_CHAR_SET[(static_cast(inputString[strLen - 2]) & 0xff) >> 2]; outputBuffer[encodedStrLen - 3] = - base64CharSet[(static_cast(inputString[strLen - 2]) & 0x03) << 4 | + BASE64_CHAR_SET[(static_cast(inputString[strLen - 2]) & 0x03) << 4 | (static_cast(inputString[strLen - 1]) & 0xf0) >> 4]; outputBuffer[encodedStrLen - 2] = - base64CharSet[(static_cast(inputString[strLen - 1]) & 0x0f) << 2]; + BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0x0f) << 2]; outputBuffer[encodedStrLen - 1] = '='; break; default: @@ -200,7 +200,7 @@ TwoByteValue::TwoByteValue(Isolate* isolate, Local value) AllocateSufficientStorage(storage); const int flags = String::NO_NULL_TERMINATION; - const int length = string->Write(isolate, out(), 0, storage, flags); + const int length = string->Write(isolate, Out(), 0, storage, flags); SetLengthAndZeroTerminate(length); } } // namespace inspector diff --git a/src/inspector/inspector_utils.h b/src/inspector/inspector_utils.h index c2c5527..7d01bd4 100644 --- a/src/inspector/inspector_utils.h +++ b/src/inspector/inspector_utils.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "jsvm_dfx.h" #include "jsvm_util.h" @@ -32,10 +33,10 @@ namespace jsvm { namespace inspector { -// // The helper is for doing safe downcasts from base types to derived types. template class ContainerOfHelper { public: + // The helper is for doing safe downcasts from base types to derived types. inline ContainerOfHelper(Inner Outer::*field, Inner* pointer); template inline operator TypeName*() const; @@ -129,18 +130,15 @@ constexpr ContainerOfHelper ContainerOf(Inner Outer::*field, Inner return ContainerOfHelper(field, pointer); } -// util.h -// Allocates an array of member type T. For up to kStackStorageSize items, -// the stack is used, otherwise malloc(). template class MaybeStackBuffer { public: - const T* out() const + const T* Out() const { return buf; } - T* out() + T* Out() { return buf; } @@ -180,10 +178,6 @@ public: return capacity; } - // Make sure enough space for `storage` entries is available. - // This method can be called multiple times throughout the lifetime of the - // buffer, but once this has been called Invalidate() cannot be used. - // Content of the buffer in the range [0, GetLength()) is preserved. void AllocateSufficientStorage(size_t storage); void SetLength(size_t lengthParam) @@ -203,10 +197,6 @@ public: buf[len] = T(); } - // Make dereferencing this object return nullptr. - // This method can be called multiple times throughout the lifetime of the - // buffer, but once this has been called AllocateSufficientStorage() cannot - // be used. void Invalidate() { CHECK(!IsAllocated()); @@ -257,11 +247,11 @@ public: inline std::basic_string ToString() const { - return { out(), GetLength() }; + return { Out(), GetLength() }; } inline std::basic_string_view ToStringView() const { - return { out(), GetLength() }; + return { Out(), GetLength() }; } private: @@ -277,7 +267,6 @@ public: explicit TwoByteValue(v8::Isolate* isolate, v8::Local value); }; -// TODO: replace realloc with Realloc template void MaybeStackBuffer::AllocateSufficientStorage(size_t storage) { @@ -285,10 +274,11 @@ void MaybeStackBuffer::AllocateSufficientStorage(size_t st if (storage > GetCapacity()) { bool wasAllocated = IsAllocated(); T* allocatedPtr = wasAllocated ? buf : nullptr; - buf = reinterpret_cast(realloc(allocatedPtr, storage)); + buf = reinterpret_cast(Realloc(allocatedPtr, storage)); capacity = storage; if (!wasAllocated && length > 0) { - memcpy(buf, bufSt, length * sizeof(buf[0])); + int ret = memcpy_s(buf, length * sizeof(buf[0]), bufSt, length * sizeof(buf[0])); + CHECK(ret == 0); } } @@ -320,4 +310,4 @@ MUST_USE_RESULT bool CSPRNG(void* buffer, size_t length); void CheckedUvLoopClose(uv_loop_t* loop); } // namespace inspector } // namespace jsvm -#endif \ No newline at end of file +#endif -- Gitee From 0facde126a705eee0fc2605677d76110ab00a59a Mon Sep 17 00:00:00 2001 From: wangyimin Date: Sat, 11 Jan 2025 17:02:42 +0800 Subject: [PATCH 3/3] fix format error Signed-off-by: wangyimin --- src/inspector/inspector_utils.cpp | 65 ++++++++++++++++----------- src/inspector/inspector_utils.h | 74 ++++++++++++++++++++++--------- 2 files changed, 91 insertions(+), 48 deletions(-) diff --git a/src/inspector/inspector_utils.cpp b/src/inspector/inspector_utils.cpp index bc2cc77..0003d83 100644 --- a/src/inspector/inspector_utils.cpp +++ b/src/inspector/inspector_utils.cpp @@ -39,7 +39,7 @@ inline icu::UnicodeString Utf8ToUtf16(const char* data, size_t len) return utf16Str; } -inline std::string Utf16toUtf8(const char16_t* data, size_t length) +inline std::string Utf16ToUtf8(const char16_t* data, size_t length) { icu::UnicodeString unicodeStr(data, length); std::string utf8Str; @@ -68,14 +68,12 @@ std::string StringViewToUtf8(v8_inspector::StringView view) } const char16_t* source = reinterpret_cast(view.characters16()); - return Utf16toUtf8(source, view.length()); + return Utf16ToUtf8(source, view.length()); } -constexpr size_t TO_TRANSFORM_CHAR_NUM = 3; -constexpr size_t TRANSFORMED_CHAR_NUM = 4; - static constexpr char BASE64_CHAR_SET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +// clang-format off size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, size_t dlen) { // 1: caluate encode size and check @@ -88,37 +86,49 @@ size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, si for (size_t i = 0, j = 0; j < strLen - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) { // convert three 8bit into four 6bit; then add two 0 bit in each 6 bit // former 00 + first 6 bits of the first char - outputBuffer[i] = BASE64_CHAR_SET[(static_cast(inputString[j]) & 0xff) >> 2]; + outputBuffer[i] = BASE64_CHAR_SET[(static_cast(inputString[j]) & 0xff) >> ByteOffset::BIT_2]; // 00 + the last 2 bits of the first char + the first 4 bits of the second char - outputBuffer[i + 1] = BASE64_CHAR_SET[(static_cast(inputString[j]) & 0x03) << 4 | - (static_cast(inputString[j + 1]) & 0xf0) >> 4]; + outputBuffer[i + ByteOffset::BYTE_1] = + BASE64_CHAR_SET[(static_cast(inputString[j]) & 0x03) << ByteOffset::BIT_4 | + (static_cast(inputString[j + ByteOffset::BYTE_1]) & 0xf0) >> + ByteOffset::BIT_4]; // 00 + last 4 bits of the second char + the first 2 bits of the third char - outputBuffer[i + 2] = BASE64_CHAR_SET[(static_cast(inputString[j + 1]) & 0x0f) << 2 | - (static_cast(inputString[j + 2]) & 0xc0) >> 6]; + outputBuffer[i + ByteOffset::BYTE_2] = + BASE64_CHAR_SET[(static_cast(inputString[j + ByteOffset::BYTE_1]) & 0x0f) << + ByteOffset::BIT_2 | + (static_cast(inputString[j + ByteOffset::BYTE_2]) & 0xc0) >> + ByteOffset::BIT_6]; // 00 + the last 6 bits of the third char - outputBuffer[i + 3] = BASE64_CHAR_SET[static_cast(inputString[j + 2]) & 0x3f]; + outputBuffer[i + ByteOffset::BYTE_3] = + BASE64_CHAR_SET[static_cast(inputString[j + ByteOffset::BYTE_2]) & 0x3f]; } switch (strLen % TO_TRANSFORM_CHAR_NUM) { // the original string is less than three bytes, and the missing place is filled with '=' to patch four bytes - case 1: + case ByteSize::SIZE_1_BYTES: // 1,2: the original character is one, and two characters are missing after conversion - outputBuffer[encodedStrLen - 4] = - BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0xff) >> 2]; - outputBuffer[encodedStrLen - 3] = - BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0x03) << 4]; - outputBuffer[encodedStrLen - 2] = '='; - outputBuffer[encodedStrLen - 1] = '='; + outputBuffer[encodedStrLen - ByteOffset::BYTE_4] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - ByteOffset::BYTE_1]) & 0xff) >> + ByteOffset::BIT_2]; + outputBuffer[encodedStrLen - ByteOffset::BYTE_3] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - ByteOffset::BYTE_1]) & 0x03) << + ByteOffset::BIT_4]; + outputBuffer[encodedStrLen - ByteOffset::BYTE_2] = '='; + outputBuffer[encodedStrLen - ByteOffset::BYTE_1] = '='; break; - case 2: + case ByteSize::SIZE_2_BYTES: // 1: the original character is two, and a character are missing after conversion - outputBuffer[encodedStrLen - 4] = - BASE64_CHAR_SET[(static_cast(inputString[strLen - 2]) & 0xff) >> 2]; - outputBuffer[encodedStrLen - 3] = - BASE64_CHAR_SET[(static_cast(inputString[strLen - 2]) & 0x03) << 4 | - (static_cast(inputString[strLen - 1]) & 0xf0) >> 4]; - outputBuffer[encodedStrLen - 2] = - BASE64_CHAR_SET[(static_cast(inputString[strLen - 1]) & 0x0f) << 2]; - outputBuffer[encodedStrLen - 1] = '='; + outputBuffer[encodedStrLen - ByteOffset::BYTE_4] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - ByteOffset::BYTE_2]) & 0xff) >> + ByteOffset::BIT_2]; + outputBuffer[encodedStrLen - ByteOffset::BYTE_3] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - ByteOffset::BYTE_2]) & 0x03) << + ByteOffset::BIT_4 | + (static_cast(inputString[strLen - ByteOffset::BYTE_1]) & 0xf0) >> + ByteOffset::BIT_4]; + outputBuffer[encodedStrLen - ByteOffset::BYTE_2] = + BASE64_CHAR_SET[(static_cast(inputString[strLen - ByteOffset::BYTE_1]) & 0x0f) << + ByteOffset::BIT_2]; + outputBuffer[encodedStrLen - ByteOffset::BYTE_1] = '='; break; default: break; @@ -126,6 +136,7 @@ size_t Base64Encode(const char* inputString, size_t slen, char* outputBuffer, si return encodedStrLen; } +// clang-format on std::string GetHumanReadableProcessName() { diff --git a/src/inspector/inspector_utils.h b/src/inspector/inspector_utils.h index 7d01bd4..f82f619 100644 --- a/src/inspector/inspector_utils.h +++ b/src/inspector/inspector_utils.h @@ -16,9 +16,9 @@ #ifndef INSPECTOR_UTILS_H #define INSPECTOR_UTILS_H #include +#include #include #include -#include #include "jsvm_dfx.h" #include "jsvm_util.h" @@ -37,7 +37,7 @@ template class ContainerOfHelper { public: // The helper is for doing safe downcasts from base types to derived types. - inline ContainerOfHelper(Inner Outer::*field, Inner* pointer); + inline ContainerOfHelper(Inner Outer::* field, Inner* pointer); template inline operator TypeName*() const; @@ -79,19 +79,6 @@ template inline void USE(T&&) {} -// Used to be a macro, hence the uppercase name. -template -inline v8::Local FIXED_ONE_BYTE_STRING(v8::Isolate* isolate, const char (&data)[N]) -{ - return OneByteString(isolate, data, N - 1); -} - -template -inline v8::Local FIXED_ONE_BYTE_STRING(v8::Isolate* isolate, const std::array& arr) -{ - return OneByteString(isolate, arr.data(), N - 1); -} - template struct FunctionDeleter { void operator()(T* pointer) const @@ -105,13 +92,13 @@ template using DeleteFnPtr = typename FunctionDeleter::Pointer; template -constexpr uintptr_t OffsetOf(Inner Outer::*field) +constexpr uintptr_t OffsetOf(Inner Outer::* field) { return reinterpret_cast(&(static_cast(nullptr)->*field)); } template -ContainerOfHelper::ContainerOfHelper(Inner Outer::*field, Inner* pointer) +ContainerOfHelper::ContainerOfHelper(Inner Outer::* field, Inner* pointer) : pointer(reinterpret_cast(reinterpret_cast(pointer) - OffsetOf(field))) {} @@ -125,7 +112,7 @@ ContainerOfHelper::operator TypeName*() const // Calculate the address of the outer (i.e. embedding) struct from // the interior pointer to a data member. template -constexpr ContainerOfHelper ContainerOf(Inner Outer::*field, Inner* pointer) +constexpr ContainerOfHelper ContainerOf(Inner Outer::* field, Inner* pointer) { return ContainerOfHelper(field, pointer); } @@ -267,6 +254,28 @@ public: explicit TwoByteValue(v8::Isolate* isolate, v8::Local value); }; +template +T* Realloc(T* pointer, size_t n, size_t oldN) +{ + CHECK(n > 0); + size_t newSize = sizeof(T) * n; + T* newPtr = static_cast(malloc(newSize)); + + CHECK_NOT_NULL(newPtr); + + if (!pointer) { + return newPtr; + } + + size_t oldSize = sizeof(T) * oldN; + CHECK(newSize > oldSize); + errno_t ret = memcpy_s(newPtr, newSize, pointer, oldSize); + CHECK(ret == EOK); + free(pointer); + + return newPtr; +} + template void MaybeStackBuffer::AllocateSufficientStorage(size_t storage) { @@ -274,11 +283,11 @@ void MaybeStackBuffer::AllocateSufficientStorage(size_t st if (storage > GetCapacity()) { bool wasAllocated = IsAllocated(); T* allocatedPtr = wasAllocated ? buf : nullptr; - buf = reinterpret_cast(Realloc(allocatedPtr, storage)); + buf = Realloc(allocatedPtr, storage, length); capacity = storage; if (!wasAllocated && length > 0) { int ret = memcpy_s(buf, length * sizeof(buf[0]), bufSt, length * sizeof(buf[0])); - CHECK(ret == 0); + CHECK(ret == EOK); } } @@ -289,10 +298,33 @@ void MaybeStackBuffer::AllocateSufficientStorage(size_t st std::string StringViewToUtf8(v8_inspector::StringView view); std::unique_ptr Utf8ToStringView(const std::string_view message); +constexpr size_t TO_TRANSFORM_CHAR_NUM = 3; +constexpr size_t TRANSFORMED_CHAR_NUM = 4; + +enum ByteOffset : uint8_t { + BYTE_0 = 0, + BYTE_1 = 1, + BYTE_2 = 2, + BYTE_3 = 3, + BYTE_4 = 4, + BYTE_5 = 5, + BYTE_6 = 6, + BYTE_7 = 7, + BIT_0 = 0, + BIT_1 = 1, + BIT_2 = 2, + BIT_3 = 3, + BIT_4 = 4, + BIT_5 = 5, + BIT_6 = 6, + BIT_7 = 7, + BIT_8 = 8, +}; + // Encode base64 inline constexpr size_t Base64EncodeSize(size_t size) { - return ((size + 2) / 3 * 4); + return ((size + TO_TRANSFORM_CHAR_NUM - 1) / TO_TRANSFORM_CHAR_NUM * TRANSFORMED_CHAR_NUM); } // Be careful: If dlen is less than expected encode size, it will crash. -- Gitee