11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/inspector/string-util.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <cinttypes> 81cb0ef41Sopenharmony_ci#include <cmath> 91cb0ef41Sopenharmony_ci#include <cstddef> 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h" 121cb0ef41Sopenharmony_ci#include "src/inspector/protocol/Protocol.h" 131cb0ef41Sopenharmony_ci#include "src/numbers/conversions.h" 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cinamespace v8_inspector { 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_cinamespace protocol { 181cb0ef41Sopenharmony_cinamespace { 191cb0ef41Sopenharmony_cistd::pair<uint8_t, uint8_t> SplitByte(uint8_t byte, uint8_t split) { 201cb0ef41Sopenharmony_ci return {byte >> split, (byte & ((1 << split) - 1)) << (6 - split)}; 211cb0ef41Sopenharmony_ci} 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_civ8::Maybe<uint8_t> DecodeByte(char byte) { 241cb0ef41Sopenharmony_ci if ('A' <= byte && byte <= 'Z') return v8::Just<uint8_t>(byte - 'A'); 251cb0ef41Sopenharmony_ci if ('a' <= byte && byte <= 'z') return v8::Just<uint8_t>(byte - 'a' + 26); 261cb0ef41Sopenharmony_ci if ('0' <= byte && byte <= '9') 271cb0ef41Sopenharmony_ci return v8::Just<uint8_t>(byte - '0' + 26 + 26); 281cb0ef41Sopenharmony_ci if (byte == '+') return v8::Just<uint8_t>(62); 291cb0ef41Sopenharmony_ci if (byte == '/') return v8::Just<uint8_t>(63); 301cb0ef41Sopenharmony_ci return v8::Nothing<uint8_t>(); 311cb0ef41Sopenharmony_ci} 321cb0ef41Sopenharmony_ci} // namespace 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciString Binary::toBase64() const { 351cb0ef41Sopenharmony_ci const char* table = 361cb0ef41Sopenharmony_ci "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 371cb0ef41Sopenharmony_ci if (size() == 0) return {}; 381cb0ef41Sopenharmony_ci std::basic_string<UChar> result; 391cb0ef41Sopenharmony_ci result.reserve(4 * ((size() + 2) / 3)); 401cb0ef41Sopenharmony_ci uint8_t last = 0; 411cb0ef41Sopenharmony_ci for (size_t n = 0; n < size();) { 421cb0ef41Sopenharmony_ci auto split = SplitByte((*bytes_)[n], 2 + 2 * (n % 3)); 431cb0ef41Sopenharmony_ci result.push_back(table[split.first | last]); 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci ++n; 461cb0ef41Sopenharmony_ci if (n < size() && n % 3 == 0) { 471cb0ef41Sopenharmony_ci result.push_back(table[split.second]); 481cb0ef41Sopenharmony_ci last = 0; 491cb0ef41Sopenharmony_ci } else { 501cb0ef41Sopenharmony_ci last = split.second; 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci result.push_back(table[last]); 541cb0ef41Sopenharmony_ci while (result.size() % 4 > 0) result.push_back('='); 551cb0ef41Sopenharmony_ci return String16(std::move(result)); 561cb0ef41Sopenharmony_ci} 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci/* static */ 591cb0ef41Sopenharmony_ciBinary Binary::fromBase64(const String& base64, bool* success) { 601cb0ef41Sopenharmony_ci if (base64.isEmpty()) { 611cb0ef41Sopenharmony_ci *success = true; 621cb0ef41Sopenharmony_ci return Binary::fromSpan(nullptr, 0); 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci *success = false; 661cb0ef41Sopenharmony_ci // Fail if the length is invalid or decoding would overflow. 671cb0ef41Sopenharmony_ci if (base64.length() % 4 != 0 || base64.length() + 4 < base64.length()) { 681cb0ef41Sopenharmony_ci return Binary::fromSpan(nullptr, 0); 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci std::vector<uint8_t> result; 721cb0ef41Sopenharmony_ci result.reserve(3 * base64.length() / 4); 731cb0ef41Sopenharmony_ci char pad = '='; 741cb0ef41Sopenharmony_ci // Iterate groups of four 751cb0ef41Sopenharmony_ci for (size_t i = 0; i < base64.length(); i += 4) { 761cb0ef41Sopenharmony_ci uint8_t a = 0, b = 0, c = 0, d = 0; 771cb0ef41Sopenharmony_ci if (!DecodeByte(base64[i + 0]).To(&a)) return Binary::fromSpan(nullptr, 0); 781cb0ef41Sopenharmony_ci if (!DecodeByte(base64[i + 1]).To(&b)) return Binary::fromSpan(nullptr, 0); 791cb0ef41Sopenharmony_ci if (!DecodeByte(base64[i + 2]).To(&c)) { 801cb0ef41Sopenharmony_ci // Padding is allowed only in the group on the last two positions 811cb0ef41Sopenharmony_ci if (i + 4 < base64.length() || base64[i + 2] != pad || 821cb0ef41Sopenharmony_ci base64[i + 3] != pad) { 831cb0ef41Sopenharmony_ci return Binary::fromSpan(nullptr, 0); 841cb0ef41Sopenharmony_ci } 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci if (!DecodeByte(base64[i + 3]).To(&d)) { 871cb0ef41Sopenharmony_ci // Padding is allowed only in the group on the last two positions 881cb0ef41Sopenharmony_ci if (i + 4 < base64.length() || base64[i + 3] != pad) { 891cb0ef41Sopenharmony_ci return Binary::fromSpan(nullptr, 0); 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci result.push_back((a << 2) | (b >> 4)); 941cb0ef41Sopenharmony_ci if (base64[i + 2] != '=') result.push_back((0xFF & (b << 4)) | (c >> 2)); 951cb0ef41Sopenharmony_ci if (base64[i + 3] != '=') result.push_back((0xFF & (c << 6)) | d); 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci *success = true; 981cb0ef41Sopenharmony_ci return Binary(std::make_shared<std::vector<uint8_t>>(std::move(result))); 991cb0ef41Sopenharmony_ci} 1001cb0ef41Sopenharmony_ci} // namespace protocol 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_civ8::Local<v8::String> toV8String(v8::Isolate* isolate, const String16& string) { 1031cb0ef41Sopenharmony_ci if (string.isEmpty()) return v8::String::Empty(isolate); 1041cb0ef41Sopenharmony_ci DCHECK_GT(v8::String::kMaxLength, string.length()); 1051cb0ef41Sopenharmony_ci return v8::String::NewFromTwoByte( 1061cb0ef41Sopenharmony_ci isolate, reinterpret_cast<const uint16_t*>(string.characters16()), 1071cb0ef41Sopenharmony_ci v8::NewStringType::kNormal, static_cast<int>(string.length())) 1081cb0ef41Sopenharmony_ci .ToLocalChecked(); 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_civ8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate, 1121cb0ef41Sopenharmony_ci const String16& string) { 1131cb0ef41Sopenharmony_ci if (string.isEmpty()) return v8::String::Empty(isolate); 1141cb0ef41Sopenharmony_ci DCHECK_GT(v8::String::kMaxLength, string.length()); 1151cb0ef41Sopenharmony_ci return v8::String::NewFromTwoByte( 1161cb0ef41Sopenharmony_ci isolate, reinterpret_cast<const uint16_t*>(string.characters16()), 1171cb0ef41Sopenharmony_ci v8::NewStringType::kInternalized, 1181cb0ef41Sopenharmony_ci static_cast<int>(string.length())) 1191cb0ef41Sopenharmony_ci .ToLocalChecked(); 1201cb0ef41Sopenharmony_ci} 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_civ8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate, 1231cb0ef41Sopenharmony_ci const char* str) { 1241cb0ef41Sopenharmony_ci return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kInternalized) 1251cb0ef41Sopenharmony_ci .ToLocalChecked(); 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_civ8::Local<v8::String> toV8String(v8::Isolate* isolate, 1291cb0ef41Sopenharmony_ci const StringView& string) { 1301cb0ef41Sopenharmony_ci if (!string.length()) return v8::String::Empty(isolate); 1311cb0ef41Sopenharmony_ci DCHECK_GT(v8::String::kMaxLength, string.length()); 1321cb0ef41Sopenharmony_ci if (string.is8Bit()) 1331cb0ef41Sopenharmony_ci return v8::String::NewFromOneByte( 1341cb0ef41Sopenharmony_ci isolate, reinterpret_cast<const uint8_t*>(string.characters8()), 1351cb0ef41Sopenharmony_ci v8::NewStringType::kNormal, static_cast<int>(string.length())) 1361cb0ef41Sopenharmony_ci .ToLocalChecked(); 1371cb0ef41Sopenharmony_ci return v8::String::NewFromTwoByte( 1381cb0ef41Sopenharmony_ci isolate, reinterpret_cast<const uint16_t*>(string.characters16()), 1391cb0ef41Sopenharmony_ci v8::NewStringType::kNormal, static_cast<int>(string.length())) 1401cb0ef41Sopenharmony_ci .ToLocalChecked(); 1411cb0ef41Sopenharmony_ci} 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ciString16 toProtocolString(v8::Isolate* isolate, v8::Local<v8::String> value) { 1441cb0ef41Sopenharmony_ci if (value.IsEmpty() || value->IsNullOrUndefined()) return String16(); 1451cb0ef41Sopenharmony_ci std::unique_ptr<UChar[]> buffer(new UChar[value->Length()]); 1461cb0ef41Sopenharmony_ci value->Write(isolate, reinterpret_cast<uint16_t*>(buffer.get()), 0, 1471cb0ef41Sopenharmony_ci value->Length()); 1481cb0ef41Sopenharmony_ci return String16(buffer.get(), value->Length()); 1491cb0ef41Sopenharmony_ci} 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ciString16 toProtocolStringWithTypeCheck(v8::Isolate* isolate, 1521cb0ef41Sopenharmony_ci v8::Local<v8::Value> value) { 1531cb0ef41Sopenharmony_ci if (value.IsEmpty() || !value->IsString()) return String16(); 1541cb0ef41Sopenharmony_ci return toProtocolString(isolate, value.As<v8::String>()); 1551cb0ef41Sopenharmony_ci} 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ciString16 toString16(const StringView& string) { 1581cb0ef41Sopenharmony_ci if (!string.length()) return String16(); 1591cb0ef41Sopenharmony_ci if (string.is8Bit()) 1601cb0ef41Sopenharmony_ci return String16(reinterpret_cast<const char*>(string.characters8()), 1611cb0ef41Sopenharmony_ci string.length()); 1621cb0ef41Sopenharmony_ci return String16(string.characters16(), string.length()); 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ciStringView toStringView(const String16& string) { 1661cb0ef41Sopenharmony_ci if (string.isEmpty()) return StringView(); 1671cb0ef41Sopenharmony_ci return StringView(string.characters16(), string.length()); 1681cb0ef41Sopenharmony_ci} 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_cibool stringViewStartsWith(const StringView& string, const char* prefix) { 1711cb0ef41Sopenharmony_ci if (!string.length()) return !(*prefix); 1721cb0ef41Sopenharmony_ci if (string.is8Bit()) { 1731cb0ef41Sopenharmony_ci for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) { 1741cb0ef41Sopenharmony_ci if (string.characters8()[i] != prefix[j]) return false; 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci } else { 1771cb0ef41Sopenharmony_ci for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) { 1781cb0ef41Sopenharmony_ci if (string.characters16()[i] != prefix[j]) return false; 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci return true; 1821cb0ef41Sopenharmony_ci} 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_cinamespace { 1851cb0ef41Sopenharmony_ci// An empty string buffer doesn't own any string data; its ::string() returns a 1861cb0ef41Sopenharmony_ci// default-constructed StringView instance. 1871cb0ef41Sopenharmony_ciclass EmptyStringBuffer : public StringBuffer { 1881cb0ef41Sopenharmony_ci public: 1891cb0ef41Sopenharmony_ci StringView string() const override { return StringView(); } 1901cb0ef41Sopenharmony_ci}; 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci// Contains LATIN1 text data or CBOR encoded binary data in a vector. 1931cb0ef41Sopenharmony_ciclass StringBuffer8 : public StringBuffer { 1941cb0ef41Sopenharmony_ci public: 1951cb0ef41Sopenharmony_ci explicit StringBuffer8(std::vector<uint8_t> data) : data_(std::move(data)) {} 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci StringView string() const override { 1981cb0ef41Sopenharmony_ci return StringView(data_.data(), data_.size()); 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci private: 2021cb0ef41Sopenharmony_ci std::vector<uint8_t> data_; 2031cb0ef41Sopenharmony_ci}; 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci// Contains a 16 bit string (String16). 2061cb0ef41Sopenharmony_ciclass StringBuffer16 : public StringBuffer { 2071cb0ef41Sopenharmony_ci public: 2081cb0ef41Sopenharmony_ci explicit StringBuffer16(String16 data) : data_(std::move(data)) {} 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci StringView string() const override { 2111cb0ef41Sopenharmony_ci return StringView(data_.characters16(), data_.length()); 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci private: 2151cb0ef41Sopenharmony_ci String16 data_; 2161cb0ef41Sopenharmony_ci}; 2171cb0ef41Sopenharmony_ci} // namespace 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci// static 2201cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> StringBuffer::create(StringView string) { 2211cb0ef41Sopenharmony_ci if (string.length() == 0) return std::make_unique<EmptyStringBuffer>(); 2221cb0ef41Sopenharmony_ci if (string.is8Bit()) { 2231cb0ef41Sopenharmony_ci return std::make_unique<StringBuffer8>(std::vector<uint8_t>( 2241cb0ef41Sopenharmony_ci string.characters8(), string.characters8() + string.length())); 2251cb0ef41Sopenharmony_ci } 2261cb0ef41Sopenharmony_ci return std::make_unique<StringBuffer16>( 2271cb0ef41Sopenharmony_ci String16(string.characters16(), string.length())); 2281cb0ef41Sopenharmony_ci} 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> StringBufferFrom(String16 str) { 2311cb0ef41Sopenharmony_ci if (str.isEmpty()) return std::make_unique<EmptyStringBuffer>(); 2321cb0ef41Sopenharmony_ci return std::make_unique<StringBuffer16>(std::move(str)); 2331cb0ef41Sopenharmony_ci} 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_cistd::unique_ptr<StringBuffer> StringBufferFrom(std::vector<uint8_t> str) { 2361cb0ef41Sopenharmony_ci if (str.empty()) return std::make_unique<EmptyStringBuffer>(); 2371cb0ef41Sopenharmony_ci return std::make_unique<StringBuffer8>(std::move(str)); 2381cb0ef41Sopenharmony_ci} 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ciString16 stackTraceIdToString(uintptr_t id) { 2411cb0ef41Sopenharmony_ci String16Builder builder; 2421cb0ef41Sopenharmony_ci builder.appendNumber(static_cast<size_t>(id)); 2431cb0ef41Sopenharmony_ci return builder.toString(); 2441cb0ef41Sopenharmony_ci} 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci} // namespace v8_inspector 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_cinamespace v8_crdtp { 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ciusing v8_inspector::String16; 2511cb0ef41Sopenharmony_ciusing v8_inspector::protocol::Binary; 2521cb0ef41Sopenharmony_ciusing v8_inspector::protocol::StringUtil; 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci// static 2551cb0ef41Sopenharmony_cibool ProtocolTypeTraits<String16>::Deserialize(DeserializerState* state, 2561cb0ef41Sopenharmony_ci String16* value) { 2571cb0ef41Sopenharmony_ci auto* tokenizer = state->tokenizer(); 2581cb0ef41Sopenharmony_ci if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) { 2591cb0ef41Sopenharmony_ci const auto str = tokenizer->GetString8(); 2601cb0ef41Sopenharmony_ci *value = StringUtil::fromUTF8(str.data(), str.size()); 2611cb0ef41Sopenharmony_ci return true; 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING16) { 2641cb0ef41Sopenharmony_ci const auto str = tokenizer->GetString16WireRep(); 2651cb0ef41Sopenharmony_ci *value = StringUtil::fromUTF16LE( 2661cb0ef41Sopenharmony_ci reinterpret_cast<const uint16_t*>(str.data()), str.size() / 2); 2671cb0ef41Sopenharmony_ci return true; 2681cb0ef41Sopenharmony_ci } 2691cb0ef41Sopenharmony_ci state->RegisterError(Error::BINDINGS_STRING_VALUE_EXPECTED); 2701cb0ef41Sopenharmony_ci return false; 2711cb0ef41Sopenharmony_ci} 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci// static 2741cb0ef41Sopenharmony_civoid ProtocolTypeTraits<String16>::Serialize(const String16& value, 2751cb0ef41Sopenharmony_ci std::vector<uint8_t>* bytes) { 2761cb0ef41Sopenharmony_ci cbor::EncodeFromUTF16( 2771cb0ef41Sopenharmony_ci span<uint16_t>(reinterpret_cast<const uint16_t*>(value.characters16()), 2781cb0ef41Sopenharmony_ci value.length()), 2791cb0ef41Sopenharmony_ci bytes); 2801cb0ef41Sopenharmony_ci} 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci// static 2831cb0ef41Sopenharmony_cibool ProtocolTypeTraits<Binary>::Deserialize(DeserializerState* state, 2841cb0ef41Sopenharmony_ci Binary* value) { 2851cb0ef41Sopenharmony_ci auto* tokenizer = state->tokenizer(); 2861cb0ef41Sopenharmony_ci if (tokenizer->TokenTag() == cbor::CBORTokenTag::BINARY) { 2871cb0ef41Sopenharmony_ci const span<uint8_t> bin = tokenizer->GetBinary(); 2881cb0ef41Sopenharmony_ci *value = Binary::fromSpan(bin.data(), bin.size()); 2891cb0ef41Sopenharmony_ci return true; 2901cb0ef41Sopenharmony_ci } 2911cb0ef41Sopenharmony_ci if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) { 2921cb0ef41Sopenharmony_ci const auto str_span = tokenizer->GetString8(); 2931cb0ef41Sopenharmony_ci auto str = StringUtil::fromUTF8(str_span.data(), str_span.size()); 2941cb0ef41Sopenharmony_ci bool success = false; 2951cb0ef41Sopenharmony_ci *value = Binary::fromBase64(str, &success); 2961cb0ef41Sopenharmony_ci return success; 2971cb0ef41Sopenharmony_ci } 2981cb0ef41Sopenharmony_ci state->RegisterError(Error::BINDINGS_BINARY_VALUE_EXPECTED); 2991cb0ef41Sopenharmony_ci return false; 3001cb0ef41Sopenharmony_ci} 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci// static 3031cb0ef41Sopenharmony_civoid ProtocolTypeTraits<Binary>::Serialize(const Binary& value, 3041cb0ef41Sopenharmony_ci std::vector<uint8_t>* bytes) { 3051cb0ef41Sopenharmony_ci cbor::EncodeBinary(span<uint8_t>(value.data(), value.size()), bytes); 3061cb0ef41Sopenharmony_ci} 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ci} // namespace v8_crdtp 309