1// Copyright 2016 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/inspector/string-util.h" 6 7#include <cinttypes> 8#include <cmath> 9#include <cstddef> 10 11#include "src/base/platform/platform.h" 12#include "src/inspector/protocol/Protocol.h" 13#include "src/numbers/conversions.h" 14 15namespace v8_inspector { 16 17namespace protocol { 18namespace { 19std::pair<uint8_t, uint8_t> SplitByte(uint8_t byte, uint8_t split) { 20 return {byte >> split, (byte & ((1 << split) - 1)) << (6 - split)}; 21} 22 23v8::Maybe<uint8_t> DecodeByte(char byte) { 24 if ('A' <= byte && byte <= 'Z') return v8::Just<uint8_t>(byte - 'A'); 25 if ('a' <= byte && byte <= 'z') return v8::Just<uint8_t>(byte - 'a' + 26); 26 if ('0' <= byte && byte <= '9') 27 return v8::Just<uint8_t>(byte - '0' + 26 + 26); 28 if (byte == '+') return v8::Just<uint8_t>(62); 29 if (byte == '/') return v8::Just<uint8_t>(63); 30 return v8::Nothing<uint8_t>(); 31} 32} // namespace 33 34String Binary::toBase64() const { 35 const char* table = 36 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 37 if (size() == 0) return {}; 38 std::basic_string<UChar> result; 39 result.reserve(4 * ((size() + 2) / 3)); 40 uint8_t last = 0; 41 for (size_t n = 0; n < size();) { 42 auto split = SplitByte((*bytes_)[n], 2 + 2 * (n % 3)); 43 result.push_back(table[split.first | last]); 44 45 ++n; 46 if (n < size() && n % 3 == 0) { 47 result.push_back(table[split.second]); 48 last = 0; 49 } else { 50 last = split.second; 51 } 52 } 53 result.push_back(table[last]); 54 while (result.size() % 4 > 0) result.push_back('='); 55 return String16(std::move(result)); 56} 57 58/* static */ 59Binary Binary::fromBase64(const String& base64, bool* success) { 60 if (base64.isEmpty()) { 61 *success = true; 62 return Binary::fromSpan(nullptr, 0); 63 } 64 65 *success = false; 66 // Fail if the length is invalid or decoding would overflow. 67 if (base64.length() % 4 != 0 || base64.length() + 4 < base64.length()) { 68 return Binary::fromSpan(nullptr, 0); 69 } 70 71 std::vector<uint8_t> result; 72 result.reserve(3 * base64.length() / 4); 73 char pad = '='; 74 // Iterate groups of four 75 for (size_t i = 0; i < base64.length(); i += 4) { 76 uint8_t a = 0, b = 0, c = 0, d = 0; 77 if (!DecodeByte(base64[i + 0]).To(&a)) return Binary::fromSpan(nullptr, 0); 78 if (!DecodeByte(base64[i + 1]).To(&b)) return Binary::fromSpan(nullptr, 0); 79 if (!DecodeByte(base64[i + 2]).To(&c)) { 80 // Padding is allowed only in the group on the last two positions 81 if (i + 4 < base64.length() || base64[i + 2] != pad || 82 base64[i + 3] != pad) { 83 return Binary::fromSpan(nullptr, 0); 84 } 85 } 86 if (!DecodeByte(base64[i + 3]).To(&d)) { 87 // Padding is allowed only in the group on the last two positions 88 if (i + 4 < base64.length() || base64[i + 3] != pad) { 89 return Binary::fromSpan(nullptr, 0); 90 } 91 } 92 93 result.push_back((a << 2) | (b >> 4)); 94 if (base64[i + 2] != '=') result.push_back((0xFF & (b << 4)) | (c >> 2)); 95 if (base64[i + 3] != '=') result.push_back((0xFF & (c << 6)) | d); 96 } 97 *success = true; 98 return Binary(std::make_shared<std::vector<uint8_t>>(std::move(result))); 99} 100} // namespace protocol 101 102v8::Local<v8::String> toV8String(v8::Isolate* isolate, const String16& string) { 103 if (string.isEmpty()) return v8::String::Empty(isolate); 104 DCHECK_GT(v8::String::kMaxLength, string.length()); 105 return v8::String::NewFromTwoByte( 106 isolate, reinterpret_cast<const uint16_t*>(string.characters16()), 107 v8::NewStringType::kNormal, static_cast<int>(string.length())) 108 .ToLocalChecked(); 109} 110 111v8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate, 112 const String16& string) { 113 if (string.isEmpty()) return v8::String::Empty(isolate); 114 DCHECK_GT(v8::String::kMaxLength, string.length()); 115 return v8::String::NewFromTwoByte( 116 isolate, reinterpret_cast<const uint16_t*>(string.characters16()), 117 v8::NewStringType::kInternalized, 118 static_cast<int>(string.length())) 119 .ToLocalChecked(); 120} 121 122v8::Local<v8::String> toV8StringInternalized(v8::Isolate* isolate, 123 const char* str) { 124 return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kInternalized) 125 .ToLocalChecked(); 126} 127 128v8::Local<v8::String> toV8String(v8::Isolate* isolate, 129 const StringView& string) { 130 if (!string.length()) return v8::String::Empty(isolate); 131 DCHECK_GT(v8::String::kMaxLength, string.length()); 132 if (string.is8Bit()) 133 return v8::String::NewFromOneByte( 134 isolate, reinterpret_cast<const uint8_t*>(string.characters8()), 135 v8::NewStringType::kNormal, static_cast<int>(string.length())) 136 .ToLocalChecked(); 137 return v8::String::NewFromTwoByte( 138 isolate, reinterpret_cast<const uint16_t*>(string.characters16()), 139 v8::NewStringType::kNormal, static_cast<int>(string.length())) 140 .ToLocalChecked(); 141} 142 143String16 toProtocolString(v8::Isolate* isolate, v8::Local<v8::String> value) { 144 if (value.IsEmpty() || value->IsNullOrUndefined()) return String16(); 145 std::unique_ptr<UChar[]> buffer(new UChar[value->Length()]); 146 value->Write(isolate, reinterpret_cast<uint16_t*>(buffer.get()), 0, 147 value->Length()); 148 return String16(buffer.get(), value->Length()); 149} 150 151String16 toProtocolStringWithTypeCheck(v8::Isolate* isolate, 152 v8::Local<v8::Value> value) { 153 if (value.IsEmpty() || !value->IsString()) return String16(); 154 return toProtocolString(isolate, value.As<v8::String>()); 155} 156 157String16 toString16(const StringView& string) { 158 if (!string.length()) return String16(); 159 if (string.is8Bit()) 160 return String16(reinterpret_cast<const char*>(string.characters8()), 161 string.length()); 162 return String16(string.characters16(), string.length()); 163} 164 165StringView toStringView(const String16& string) { 166 if (string.isEmpty()) return StringView(); 167 return StringView(string.characters16(), string.length()); 168} 169 170bool stringViewStartsWith(const StringView& string, const char* prefix) { 171 if (!string.length()) return !(*prefix); 172 if (string.is8Bit()) { 173 for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) { 174 if (string.characters8()[i] != prefix[j]) return false; 175 } 176 } else { 177 for (size_t i = 0, j = 0; prefix[j] && i < string.length(); ++i, ++j) { 178 if (string.characters16()[i] != prefix[j]) return false; 179 } 180 } 181 return true; 182} 183 184namespace { 185// An empty string buffer doesn't own any string data; its ::string() returns a 186// default-constructed StringView instance. 187class EmptyStringBuffer : public StringBuffer { 188 public: 189 StringView string() const override { return StringView(); } 190}; 191 192// Contains LATIN1 text data or CBOR encoded binary data in a vector. 193class StringBuffer8 : public StringBuffer { 194 public: 195 explicit StringBuffer8(std::vector<uint8_t> data) : data_(std::move(data)) {} 196 197 StringView string() const override { 198 return StringView(data_.data(), data_.size()); 199 } 200 201 private: 202 std::vector<uint8_t> data_; 203}; 204 205// Contains a 16 bit string (String16). 206class StringBuffer16 : public StringBuffer { 207 public: 208 explicit StringBuffer16(String16 data) : data_(std::move(data)) {} 209 210 StringView string() const override { 211 return StringView(data_.characters16(), data_.length()); 212 } 213 214 private: 215 String16 data_; 216}; 217} // namespace 218 219// static 220std::unique_ptr<StringBuffer> StringBuffer::create(StringView string) { 221 if (string.length() == 0) return std::make_unique<EmptyStringBuffer>(); 222 if (string.is8Bit()) { 223 return std::make_unique<StringBuffer8>(std::vector<uint8_t>( 224 string.characters8(), string.characters8() + string.length())); 225 } 226 return std::make_unique<StringBuffer16>( 227 String16(string.characters16(), string.length())); 228} 229 230std::unique_ptr<StringBuffer> StringBufferFrom(String16 str) { 231 if (str.isEmpty()) return std::make_unique<EmptyStringBuffer>(); 232 return std::make_unique<StringBuffer16>(std::move(str)); 233} 234 235std::unique_ptr<StringBuffer> StringBufferFrom(std::vector<uint8_t> str) { 236 if (str.empty()) return std::make_unique<EmptyStringBuffer>(); 237 return std::make_unique<StringBuffer8>(std::move(str)); 238} 239 240String16 stackTraceIdToString(uintptr_t id) { 241 String16Builder builder; 242 builder.appendNumber(static_cast<size_t>(id)); 243 return builder.toString(); 244} 245 246} // namespace v8_inspector 247 248namespace v8_crdtp { 249 250using v8_inspector::String16; 251using v8_inspector::protocol::Binary; 252using v8_inspector::protocol::StringUtil; 253 254// static 255bool ProtocolTypeTraits<String16>::Deserialize(DeserializerState* state, 256 String16* value) { 257 auto* tokenizer = state->tokenizer(); 258 if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) { 259 const auto str = tokenizer->GetString8(); 260 *value = StringUtil::fromUTF8(str.data(), str.size()); 261 return true; 262 } 263 if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING16) { 264 const auto str = tokenizer->GetString16WireRep(); 265 *value = StringUtil::fromUTF16LE( 266 reinterpret_cast<const uint16_t*>(str.data()), str.size() / 2); 267 return true; 268 } 269 state->RegisterError(Error::BINDINGS_STRING_VALUE_EXPECTED); 270 return false; 271} 272 273// static 274void ProtocolTypeTraits<String16>::Serialize(const String16& value, 275 std::vector<uint8_t>* bytes) { 276 cbor::EncodeFromUTF16( 277 span<uint16_t>(reinterpret_cast<const uint16_t*>(value.characters16()), 278 value.length()), 279 bytes); 280} 281 282// static 283bool ProtocolTypeTraits<Binary>::Deserialize(DeserializerState* state, 284 Binary* value) { 285 auto* tokenizer = state->tokenizer(); 286 if (tokenizer->TokenTag() == cbor::CBORTokenTag::BINARY) { 287 const span<uint8_t> bin = tokenizer->GetBinary(); 288 *value = Binary::fromSpan(bin.data(), bin.size()); 289 return true; 290 } 291 if (tokenizer->TokenTag() == cbor::CBORTokenTag::STRING8) { 292 const auto str_span = tokenizer->GetString8(); 293 auto str = StringUtil::fromUTF8(str_span.data(), str_span.size()); 294 bool success = false; 295 *value = Binary::fromBase64(str, &success); 296 return success; 297 } 298 state->RegisterError(Error::BINDINGS_BINARY_VALUE_EXPECTED); 299 return false; 300} 301 302// static 303void ProtocolTypeTraits<Binary>::Serialize(const Binary& value, 304 std::vector<uint8_t>* bytes) { 305 cbor::EncodeBinary(span<uint8_t>(value.data(), value.size()), bytes); 306} 307 308} // namespace v8_crdtp 309