void String::unserialize(VariableUnserializer *uns, char delimiter0 /* = '"' */, char delimiter1 /* = '"' */) { int64_t size = uns->readInt(); if (size >= RuntimeOption::MaxSerializedStringSize) { throw Exception("Size of serialized string (%d) exceeds max", int(size)); } if (size < 0) { throw Exception("Size of serialized string (%d) must not be negative", int(size)); } char ch = uns->readChar(); if (ch != ':') { throw Exception("Expected ':' but got '%c'", ch); } ch = uns->readChar(); if (ch != delimiter0) { throw Exception("Expected '%c' but got '%c'", delimiter0, ch); } StringData *px = NEW(StringData)(int(size)); MutableSlice buf = px->mutableSlice(); assert(size <= buf.len); uns->read(buf.ptr, size); px->setSize(size); if (m_px) decRefStr(m_px); m_px = px; px->setRefCount(1); ch = uns->readChar(); if (ch != delimiter1) { throw Exception("Expected '%c' but got '%c'", delimiter1, ch); } }
void String::unserialize(VariableUnserializer *uns, char delimiter0 /* = '"' */, char delimiter1 /* = '"' */) { int64_t size = uns->readInt(); if (size >= RuntimeOption::MaxSerializedStringSize) { throw Exception("Size of serialized string (%d) exceeds max", int(size)); } if (size < 0) { throw Exception("Size of serialized string (%d) must not be negative", int(size)); } uns->expectChar(':'); uns->expectChar(delimiter0); StringData *px = StringData::Make(int(size)); auto const buf = px->bufferSlice(); assert(size <= buf.len); uns->read(buf.ptr, size); px->setSize(size); if (m_px) decRefStr(m_px); m_px = px; px->setRefCount(1); uns->expectChar(delimiter1); }
String concat3(const String& s1, const String& s2, const String& s3) { StringSlice r1 = s1.slice(); StringSlice r2 = s2.slice(); StringSlice r3 = s3.slice(); int len = r1.len + r2.len + r3.len; StringData* str = StringData::Make(len); auto const r = str->bufferSlice(); memcpy(r.ptr, r1.ptr, r1.len); memcpy(r.ptr + r1.len, r2.ptr, r2.len); memcpy(r.ptr + r1.len + r2.len, r3.ptr, r3.len); str->setSize(len); return str; }
String StringBuffer::detach() { if (m_buffer && m_len) { assert(m_str && m_str->getCount() == 0); m_buffer[m_len] = '\0'; // fixup StringData* str = m_str; str->setSize(m_len); m_str = 0; m_buffer = 0; m_len = 0; m_cap = 0; return String(str); // causes incref } return empty_string(); }
String StringBuffer::detachImpl() { TAINT_OBSERVER_REGISTER_ACCESSED(m_taint_data); #ifdef TAINTED m_taint_data.unsetTaint(TAINT_BIT_ALL); #endif if (m_buffer && m_len) { ASSERT(m_str && m_str->getCount() == 0); m_buffer[m_len] = '\0'; // fixup StringData* str = m_str; str->setSize(m_len); m_str = 0; m_buffer = 0; m_len = 0; m_cap = 0; return String(str); // causes incref } return String(""); }
Variant xdebug_get_php_symbol(ActRec* ar, StringData* name) { int state; auto slice = name->slice(); const char *p = slice.begin(); const char *end = slice.end(); const char *keyword = nullptr; const char *keyword_end = nullptr; Class* ctx = nullptr; Variant sym; String key(name->size(), ReserveStringMode()); char quotechar = 0; SymbolType type = SymbolType::Root; StringData* sd = key.get(); char* keyBuf = sd->mutableData(); for (; p != end; ++p) { switch (state) { case 0: if (*p == '$') { keyword = p + 1; break; } // special tricks if (*p == ':') { keyword = p; state = 7; break; } keyword = p; state = 1; // fallthrough case 1: if (*p == '[') { keyword_end = p; if (keyword) { memcpy(keyBuf, keyword, keyword_end - keyword); sd->setSize(keyword_end - keyword); sym = xdebug_lookup_symbol(type, key, ctx, sym, ar); ctx = nullptr; keyword = nullptr; } state = 3; } else if (*p == '-') { keyword_end = p; if (keyword) { memcpy(keyBuf, keyword, keyword_end - keyword); sd->setSize(keyword_end - keyword); sym = xdebug_lookup_symbol(type, key, ctx, sym, ar); ctx = xdebug_get_sym_class(sym); keyword = nullptr; } state = 2; type = SymbolType::ObjProp; } else if (*p == ':') { keyword_end = p; if (keyword) { memcpy(keyBuf, keyword, keyword_end - keyword); sd->setSize(keyword_end - keyword); // XXX: this call is going to set ctx sym = xdebug_lookup_symbol(type, key, ctx, sym, ar); keyword = nullptr; } state = 8; type = SymbolType::StaticProp; } break; case 2: if (*p != '>') { keyword = p; state = 1; } break; case 8: if (*p != ':') { keyword = p; state = 1; } break; // Parsing in [...] case 3: // Associative arrays if (*p == '\'' || *p == '"') { state = 4; keyword = p + 1; quotechar = *p; type = SymbolType::ArrayIndexAssoc; } // Numerical index if (*p >= '0' && *p <= '9') { state = 6; keyword = p; type = SymbolType::ArrayIndexNum; } // Numerical index starting with a - if (*p == '-') { state = 9; keyword = p; } break; // Numerical index starting with a - case 9: if (*p >= '0' && *p <= '9') { state = 6; type = SymbolType::ArrayIndexNum; } break; case 4: if (*p == quotechar) { quotechar = 0; state = 5; keyword_end = p; memcpy(keyBuf, keyword, keyword_end - keyword); sd->setSize(keyword_end - keyword); sym = xdebug_lookup_symbol(type, key, ctx, sym, ar); ctx = xdebug_get_sym_class(sym); keyword = nullptr; } break; case 5: if (*p == ']') { state = 1; } break; case 6: if (*p == ']') { state = 1; keyword_end = p; memcpy(keyBuf, keyword, keyword_end - keyword); sd->setSize(keyword_end - keyword); sym = xdebug_lookup_symbol(type, key, ctx, sym, ar); ctx = xdebug_get_sym_class(sym); keyword = nullptr; } break; // special cases, started with a ":" case 7: if (*p == ':') { state = 1; keyword_end = p; // static class properties if (keyword_end + 1 != end && strncmp(keyword, "::", 2) == 0) { ctx = ar->hasClass() ? ar->getClass() : ar->hasThis() ? ar->getThis()->getVMClass() : nullptr; sym = uninit_null(); keyword = p + 1; type = SymbolType::StaticRoot; } else { keyword = nullptr; } } break; } } if (keyword) { memcpy(keyBuf, keyword, p - keyword); sd->setSize(p - keyword); sym = xdebug_lookup_symbol(type, key, ctx, sym, ar); } return sym; }