String Variant::toStringHelper() const { switch (m_type) { case KindOfUninit: case KindOfNull: return empty_string(); case KindOfBoolean: return m_data.num ? static_cast<String>(s_1) : empty_string(); case KindOfInt64: return m_data.num; case KindOfDouble: return m_data.dbl; case KindOfStaticString: case KindOfString: assert(false); // Should be done in caller return m_data.pstr; case KindOfArray: raise_notice("Array to string conversion"); return array_string; case KindOfObject: return m_data.pobj->invokeToString(); case KindOfResource: return m_data.pres->o_toString(); case KindOfRef: return m_data.pref->var()->toString(); case KindOfClass: break; } not_reached(); }
static Variant str_replace(CVarRef search, CVarRef replace, CStrRef subject, int &count, bool caseSensitive) { if (search.is(KindOfArray)) { String ret = subject; Array searchArr = search.toArray(); if (replace.is(KindOfArray)) { Array replArr = replace.toArray(); ArrayIter replIter(replArr); for (ArrayIter iter(searchArr); iter; ++iter) { TAINT_OBSERVER(TAINT_BIT_MUTATED, TAINT_BIT_NONE); if (replIter) { ret = ret.replace(iter.second().toString(), replIter.second().toString(), count, caseSensitive); ++replIter; } else { ret = ret.replace(iter.second().toString(), "", count, caseSensitive); } } return ret; } TAINT_OBSERVER(TAINT_BIT_MUTATED, TAINT_BIT_NONE); String repl = replace.toString(); for (ArrayIter iter(searchArr); iter; ++iter) { ret = ret.replace(iter.second().toString(), repl, count, caseSensitive); } return ret; } if (replace.is(KindOfArray)) { raise_notice("Array to string conversion"); } TAINT_OBSERVER(TAINT_BIT_MUTATED, TAINT_BIT_NONE); return subject.replace(search.toString(), replace.toString(), count, caseSensitive); }
bool MySQL::connect(const String& host, int port, const String& socket, const String& username, const String& password, const String& database, int client_flags, int connect_timeout) { if (m_conn == nullptr) { m_conn = create_new_conn(); } if (connect_timeout >= 0) { MySQLUtil::set_mysql_timeout(m_conn, MySQLUtil::ConnectTimeout, connect_timeout); } if (RuntimeOption::EnableStats && RuntimeOption::EnableSQLStats) { ServerStats::Log("sql.conn", 1); } IOStatusHelper io("mysql::connect", host.data(), port); m_xaction_count = 0; if (m_host.empty()) m_host = static_cast<std::string>(host); if (m_username.empty()) m_username = static_cast<std::string>(username); if (m_password.empty()) m_password = static_cast<std::string>(password); if (m_socket.empty()) m_socket = static_cast<std::string>(socket); if (m_database.empty()) m_database = static_cast<std::string>(database); if (!m_port) m_port = port; bool ret = mysql_real_connect(m_conn, host.data(), username.data(), password.data(), (database.empty() ? nullptr : database.data()), port, socket.empty() ? nullptr : socket.data(), client_flags); if (ret && mysqlExtension::WaitTimeout > 0) { String query("set session wait_timeout="); query += String((int64_t)(mysqlExtension::WaitTimeout / 1000)); if (mysql_real_query(m_conn, query.data(), query.size())) { raise_notice("MySQL::connect: failed setting session wait timeout: %s", mysql_error(m_conn)); } } m_state = (ret) ? MySQLState::CONNECTED : MySQLState::CLOSED; return ret; }
XDEBUG_NOTIMPLEMENTED static void HHVM_FUNCTION(xdebug_start_code_coverage, int64_t options /* = 0 */) { // XDEBUG_CC_UNUSED and XDEBUG_CC_DEAD_CODE not supported right now primarily // because the internal CodeCoverage class does support either unexecuted line // tracking or dead code analysis if (options != 0) { raise_error("XDEBUG_CC_UNUSED and XDEBUG_CC_DEAD_CODE constants are not " "currently supported."); return; } // If we get here, turn on coverage auto ti = ThreadInfo::s_threadInfo.getNoCheck(); ti->m_reqInjectionData.setCoverage(true); if (g_context->isNested()) { raise_notice("Calling xdebug_start_code_coverage from a nested VM instance " "may cause unpredicable results"); } throw VMSwitchModeBuiltin(); }
void tvCastToStringInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); StringData * s; switch (tv->m_type) { case KindOfUninit: case KindOfNull: s = staticEmptyString(); goto static_string; case KindOfBoolean: s = tv->m_data.num ? s_1.get() : staticEmptyString(); goto static_string; case KindOfInt64: s = buildStringData(tv->m_data.num); break; case KindOfDouble: s = buildStringData(tv->m_data.dbl); break; case KindOfStaticString: case KindOfString: return; case KindOfArray: raise_notice("Array to string conversion"); s = array_string.get(); tvDecRefArr(tv); goto static_string; case KindOfObject: // For objects, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pobj->invokeToString(); return; case KindOfResource: // For resources, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pres->o_toString(); return; default: not_reached(); } s->incRefCount(); tv->m_data.pstr = s; tv->m_type = KindOfString; return; static_string: tv->m_data.pstr = s; tv->m_type = KindOfStaticString; }
Variant HHVM_METHOD(XMLReader, expand, const Variant& basenode /* = null */) { auto* data = Native::data<XMLReader>(this_); Object doc; xmlDocPtr docp = nullptr; SYNC_VM_REGS_SCOPED(); if (!basenode.isNull()) { DOMNode *dombasenode = toDOMNode(basenode.toObject().get()); doc = dombasenode->doc(); docp = (xmlDocPtr) toDOMNode(doc.get())->m_node; if (docp == nullptr) { raise_warning("Invalid State Error"); return false; } } else { doc = DOMDocument::newInstance(); } if (data->m_ptr) { xmlNodePtr node = xmlTextReaderExpand(data->m_ptr); if (node == nullptr) { raise_warning("An Error Occurred while expanding"); return false; } else { xmlNodePtr nodec = xmlDocCopyNode(node, docp, 1); if (nodec == nullptr) { raise_notice("Cannot expand this node type"); return false; } else { return php_dom_create_object(nodec, doc, false); } } } raise_warning("Load Data before trying to read"); return false; }
bool TimeZone::SetCurrent(const char* name) { bool valid; auto const it = s_tzvCache->find(name); if (it != s_tzvCache->end()) { valid = it->second; } else { valid = IsValid(name); auto key = strdup(name); auto result = s_tzvCache->insert(TimeZoneValidityCacheEntry(key, valid)); if (!result.second) { // The cache is full or a collision occurred, and we don't need our // strdup'ed key. free(key); } } if (!valid) { raise_notice("Timezone ID '%s' is invalid", name); return false; } RID().setTimeZone(name); return true; }
static Variant warn_non_object() { raise_notice("Cannot access property on non-object"); return uninit_null(); }
void raise_hackarr_compat_notice(const std::string& msg) { if (UNLIKELY(RID().getSuppressHackArrayCompatNotices())) return; raise_notice("Hack Array Compat: %s", msg.c_str()); }
void raise_intish_index_cast() { if (UNLIKELY(RID().getSuppressHackArrayCompatNotices())) return; raise_notice("Hack Array Compat: Intish index cast"); }
void raiseArrayKeyNotice(const StringData* key, bool isInOut) { raise_notice("Undefined index%s: %s", isInOut ? " on inout parameter" : "", key->data()); }
static DataType collator_is_numeric(UChar *str, int length, int64_t *lval, double *dval, int allow_errors ) { int64_t local_lval; double local_dval; UChar *end_ptr_long, *end_ptr_double; int conv_base=10; if (!length) { return KindOfNull; } /* handle hex numbers */ if (length>=2 && str[0]=='0' && (str[1]=='x' || str[1]=='X')) { conv_base=16; } errno=0; local_lval = collator_u_strtol(str, &end_ptr_long, conv_base); if (errno != ERANGE) { if (end_ptr_long == str+length) { /* integer string */ if (lval) { *lval = local_lval; } return KindOfInt64; } else if (end_ptr_long == str && *end_ptr_long != '\0' && *str != '.' && *str != '-') { /* ignore partial string matches */ return KindOfNull; } } else { end_ptr_long = nullptr; } if (conv_base == 16) { /* hex string, under UNIX strtod() messes it up */ /* UTODO: keep compatibility with is_numeric_string() here? */ return KindOfNull; } local_dval = collator_u_strtod(str, &end_ptr_double); if (local_dval == 0 && end_ptr_double == str) { end_ptr_double = nullptr; } else { if (end_ptr_double == str+length) { /* floating point string */ if (!finite(local_dval)) { /* "inf","nan" and maybe other weird ones */ return KindOfNull; } if (dval) { *dval = local_dval; } return KindOfDouble; } } if (!allow_errors) { return KindOfNull; } if (allow_errors == -1) { raise_notice("A non well formed numeric value encountered"); } if (allow_errors) { if (end_ptr_double > end_ptr_long && dval) { *dval = local_dval; return KindOfDouble; } else if (end_ptr_long && lval) { *lval = local_lval; return KindOfInt64; } } return KindOfNull; }
NEVER_INLINE TypedValue arrayGetNotFound(const StringData* k) { raise_notice("Undefined index: %s", k->data()); return make_tv<KindOfNull>(); }
void raiseArrayIndexNotice(const int64_t index) { raise_notice("Undefined index: %" PRId64, index); }
TypedValue* ArrayData::nvGetNotFound(const StringData* k) { raise_notice("Undefined index: %s", k->data()); return (TypedValue*)&init_null_variant; }
TypedValue* ArrayData::nvGetNotFound(int64 k) { raise_notice("Undefined index: %" PRId64, k); return (TypedValue*)&init_null_variant; }
CVarRef ArrayData::getNotFound(const StringData* k) { raise_notice("Undefined index: %s", k->data()); return null_variant; }
CVarRef ArrayData::getNotFound(CStrRef k) { raise_notice("Undefined index: %s", k.data()); return null_variant; }
CVarRef ArrayData::getNotFound(litstr k) { raise_notice("Undefined index: %s", k); return null_variant; }
CVarRef ArrayData::getNotFound(int64 k) { raise_notice("Undefined index: %lld", k); return null_variant; }
StringData* tvCastToString(const TypedValue* tv) { assert(tvIsPlausible(*tv)); if (tv->m_type == KindOfRef) { tv = tv->m_data.pref->tv(); } switch (tv->m_type) { case KindOfUninit: case KindOfNull: return staticEmptyString(); case KindOfBoolean: return tv->m_data.num ? s_1.get() : staticEmptyString(); case KindOfInt64: return buildStringData(tv->m_data.num); case KindOfDouble: return buildStringData(tv->m_data.dbl); case KindOfPersistentString: return tv->m_data.pstr; case KindOfString: { auto s = tv->m_data.pstr; s->incRefCount(); return s; } case KindOfPersistentVec: case KindOfVec: raise_notice("Vec to string conversion"); return vec_string.get(); case KindOfPersistentDict: case KindOfDict: raise_notice("Dict to string conversion"); return dict_string.get(); case KindOfPersistentKeyset: case KindOfKeyset: raise_notice("Keyset to string conversion"); return keyset_string.get(); case KindOfPersistentArray: case KindOfArray: raise_notice("Array to string conversion"); return array_string.get(); case KindOfObject: return tv->m_data.pobj->invokeToString().detach(); case KindOfResource: return tv->m_data.pres->data()->o_toString().detach(); case KindOfRef: case KindOfClass: not_reached(); } not_reached(); }
void raiseArrayKeyNotice(const StringData* key) { raise_notice("Undefined key: %s", key->data()); }
void raiseNotice(const StringData* sd) { raise_notice("%s", sd->data()); }
void tvCastToStringInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); auto string = [&](StringData* s) { tv->m_type = KindOfString; tv->m_data.pstr = s; }; auto persistentString = [&](StringData* s) { assert(!s->isRefCounted()); tv->m_type = KindOfPersistentString; tv->m_data.pstr = s; }; switch (tv->m_type) { case KindOfUninit: case KindOfNull: return persistentString(staticEmptyString()); case KindOfBoolean: return persistentString(tv->m_data.num ? s_1.get() : staticEmptyString()); case KindOfInt64: return string(buildStringData(tv->m_data.num)); case KindOfDouble: return string(buildStringData(tv->m_data.dbl)); case KindOfPersistentString: case KindOfString: return; case KindOfVec: case KindOfPersistentVec: raise_notice("Vec to string conversion"); if (tv->m_type == KindOfVec) tvDecRefArr(tv); return persistentString(vec_string.get()); case KindOfDict: case KindOfPersistentDict: raise_notice("Dict to string conversion"); if (tv->m_type == KindOfDict) tvDecRefArr(tv); return persistentString(dict_string.get()); case KindOfKeyset: case KindOfPersistentKeyset: raise_notice("Keyset to string conversion"); if (tv->m_type == KindOfKeyset) tvDecRefArr(tv); return persistentString(keyset_string.get()); case KindOfArray: case KindOfPersistentArray: raise_notice("Array to string conversion"); if (tv->m_type == KindOfArray) tvDecRefArr(tv); return persistentString(array_string.get()); case KindOfObject: // For objects, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pobj->invokeToString(); return; case KindOfResource: // For resources, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pres->data()->o_toString(); return; case KindOfRef: case KindOfClass: break; } not_reached(); }
NEVER_INLINE TypedValue arrayGetNotFound(int64_t k) { raise_notice("Undefined index: %" PRId64, k); return make_tv<KindOfNull>(); }
const Variant& ArrayData::getNotFound(const Variant& k) { raise_notice("Undefined index: %s", k.toString().data()); return null_variant; }
void NEVER_INLINE raise_null_object_prop() { raise_notice("Trying to get property of non-object"); }
void TypeConstraint::verifyFail(const Func* func, TypedValue* tv, int id, bool useStrictTypes) const { VMRegAnchor _; std::string name = displayName(func); auto const givenType = describe_actual_type(tv, isHHType()); if (UNLIKELY(!useStrictTypes)) { if (auto dt = underlyingDataType()) { // In non-strict mode we may be able to coerce a type failure. For object // typehints there is no possible coercion in the failure case, but HNI // builtins currently only guard on kind not class so the following wil // generate false positives for objects. if (*dt != KindOfObject) { // HNI conversions implicitly unbox references, this behavior is wrong, // in particular it breaks the way type conversion works for PHP 7 // scalar type hints if (tv->m_type == KindOfRef) { auto inner = tv->m_data.pref->var()->asTypedValue(); if (tvCoerceParamInPlace(inner, *dt)) { tvAsVariant(tv) = tvAsVariant(inner); return; } } else { if (tvCoerceParamInPlace(tv, *dt)) return; } } } } else if (UNLIKELY(!func->unit()->isHHFile() && !RuntimeOption::EnableHipHopSyntax)) { // PHP 7 allows for a widening conversion from Int to Float. We still ban // this in HH files. if (auto dt = underlyingDataType()) { if (*dt == KindOfDouble && tv->m_type == KindOfInt64 && tvCoerceParamToDoubleInPlace(tv)) { return; } } } // Handle return type constraint failures if (id == ReturnId) { std::string msg; if (func->isClosureBody()) { msg = folly::format( "Value returned from {}closure must be of type {}, {} given", func->isAsync() ? "async " : "", name, givenType ).str(); } else { msg = folly::format( "Value returned from {}{} {}() must be of type {}, {} given", func->isAsync() ? "async " : "", func->preClass() ? "method" : "function", func->fullName(), name, givenType ).str(); } if (RuntimeOption::EvalCheckReturnTypeHints >= 2 && !isSoft()) { raise_return_typehint_error(msg); } else { raise_warning_unsampled(msg); } return; } // Handle implicit collection->array conversion for array parameter type // constraints auto c = tvToCell(tv); if (isArray() && !isSoft() && !func->mustBeRef(id) && c->m_type == KindOfObject && c->m_data.pobj->isCollection()) { // To ease migration, the 'array' type constraint will implicitly cast // collections to arrays, provided the type constraint is not soft and // the parameter is not by reference. We raise a notice to let the user // know that there was a type mismatch and that an implicit conversion // was performed. raise_notice( folly::format( "Argument {} to {}() must be of type {}, {} given; argument {} was " "implicitly cast to array", id + 1, func->fullName(), name, givenType, id + 1 ).str() ); tvCastToArrayInPlace(tv); return; } // Handle parameter type constraint failures if (isExtended() && isSoft()) { // Soft extended type hints raise warnings instead of recoverable // errors, to ease migration. raise_warning_unsampled( folly::format( "Argument {} to {}() must be of type {}, {} given", id + 1, func->fullName(), name, givenType ).str() ); } else if (isExtended() && isNullable()) { raise_typehint_error( folly::format( "Argument {} to {}() must be of type {}, {} given", id + 1, func->fullName(), name, givenType ).str() ); } else { auto cls = Unit::lookupClass(m_typeName); if (cls && isInterface(cls)) { raise_typehint_error( folly::format( "Argument {} passed to {}() must implement interface {}, {} given", id + 1, func->fullName(), name, givenType ).str() ); } else { raise_typehint_error( folly::format( "Argument {} passed to {}() must be an instance of {}, {} given", id + 1, func->fullName(), name, givenType ).str() ); } } }
const Variant& ArrayData::getNotFound(int64_t k) { raise_notice("Undefined index: %" PRId64, k); return null_variant; }
void raiseArrayIndexNotice(const int64_t index, bool isInOut) { raise_notice("Undefined index%s: %" PRId64, isInOut ? " on inout parameter" : "", index); }