From 99fcd4295e1d5f7ad27b639979b60b0cbe22a446 Mon Sep 17 00:00:00 2001 From: Paul Tarjan Date: Wed, 8 May 2013 22:30:40 -0700 Subject: [PATCH] canonicalize \print_r to print_r at runtime builds on D795509. This copies all the callsites where we autoload. --- hphp/runtime/ext/ext_misc.cpp | 3 +- hphp/runtime/vm/translator/targetcache.cpp | 17 +++- hphp/runtime/vm/unit.cpp | 78 +++++++++++++++---- hphp/runtime/vm/unit.h | 14 +++- hphp/test/quick/ns_invalid_class.php | 4 + hphp/test/quick/ns_invalid_class.php.expectf | 1 + hphp/test/quick/ns_invalid_const.php | 4 + hphp/test/quick/ns_invalid_const.php.expectf | 1 + hphp/test/quick/ns_invalid_func.php | 4 + hphp/test/quick/ns_invalid_func.php.expectf | 1 + hphp/test/zend/{bad => good}/zend/ns_009.php | 0 .../{bad => good}/zend/ns_009.php.expectf | 0 hphp/test/zend/{bad => good}/zend/ns_019.php | 0 .../{bad => good}/zend/ns_019.php.expectf | 0 hphp/test/zend/{bad => good}/zend/ns_032.php | 0 .../{bad => good}/zend/ns_032.php.expectf | 0 16 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 hphp/test/quick/ns_invalid_class.php create mode 100644 hphp/test/quick/ns_invalid_class.php.expectf create mode 100644 hphp/test/quick/ns_invalid_const.php create mode 100644 hphp/test/quick/ns_invalid_const.php.expectf create mode 100644 hphp/test/quick/ns_invalid_func.php create mode 100644 hphp/test/quick/ns_invalid_func.php.expectf rename hphp/test/zend/{bad => good}/zend/ns_009.php (100%) rename hphp/test/zend/{bad => good}/zend/ns_009.php.expectf (100%) rename hphp/test/zend/{bad => good}/zend/ns_019.php (100%) rename hphp/test/zend/{bad => good}/zend/ns_019.php.expectf (100%) rename hphp/test/zend/{bad => good}/zend/ns_032.php (100%) rename hphp/test/zend/{bad => good}/zend/ns_032.php.expectf (100%) diff --git a/hphp/runtime/ext/ext_misc.cpp b/hphp/runtime/ext/ext_misc.cpp index 5dccb9a5c..7a0e78d6f 100644 --- a/hphp/runtime/ext/ext_misc.cpp +++ b/hphp/runtime/ext/ext_misc.cpp @@ -15,6 +15,8 @@ +----------------------------------------------------------------------+ */ +#include "hphp/runtime/ext/ext_misc.h" + #include "hphp/runtime/base/server/server_stats.h" #include "hphp/runtime/base/util/exceptions.h" #include "hphp/runtime/base/zend/zend_pack.h" @@ -23,7 +25,6 @@ #include "hphp/runtime/base/strings.h" #include "hphp/runtime/ext/ext_class.h" #include "hphp/runtime/ext/ext_math.h" -#include "hphp/runtime/ext/ext_misc.h" #include "hphp/runtime/vm/bytecode.h" #include "hphp/util/parser/scanner.h" #include "hphp/runtime/base/class_info.h" diff --git a/hphp/runtime/vm/translator/targetcache.cpp b/hphp/runtime/vm/translator/targetcache.cpp index b20241089..13a49f985 100644 --- a/hphp/runtime/vm/translator/targetcache.cpp +++ b/hphp/runtime/vm/translator/targetcache.cpp @@ -739,6 +739,8 @@ lookupKnownClass(Class** cache, const StringData* clsName, bool isClass) { Class* cls = *cache; assert(!cls); // the caller should already have checked + assert(clsName->data()[0] != '\\'); // namespace names should be done earlier + AutoloadHandler::s_instance->invokeHandler( StrNR(const_cast(clsName))); cls = *cache; @@ -772,17 +774,30 @@ ClassCache::lookup(Handle handle, StringData *name, const void* unused) { ClassCache* thiz = cacheAtHandle(handle); Pair *pair = thiz->keyToPair(name); + String normName; const StringData* pairSd = pair->m_key; if (!stringMatches(pairSd, name)) { TRACE(1, "ClassCache miss: %s\n", name->data()); const NamedEntity *ne = Unit::GetNamedEntity(name); Class *c = Unit::lookupClass(ne); if (UNLIKELY(!c)) { - c = Unit::loadMissingClass(ne, name); + normName = normalizeNS(name); + if (normName) { + name = normName.get(); + ne = Unit::GetNamedEntity(name); + c = Unit::lookupClass(ne); + if (!c) { + c = Unit::loadMissingClass(ne, name); + } + } else { + c = Unit::loadMissingClass(ne, name); + } + if (UNLIKELY(!c)) { undefinedError(Strings::UNKNOWN_CLASS, name->data()); } } + if (pair->m_key) decRefStr(pair->m_key); pair->m_key = name; name->incRefCount(); diff --git a/hphp/runtime/vm/unit.cpp b/hphp/runtime/vm/unit.cpp index 278340061..64c83edb5 100644 --- a/hphp/runtime/vm/unit.cpp +++ b/hphp/runtime/vm/unit.cpp @@ -633,10 +633,11 @@ void Unit::defTypedef(Id id) { assert(id < m_typedefs.size()); auto thisType = &m_typedefs[id]; auto nameList = GetNamedEntity(thisType->m_name); + const StringData* typeName = thisType->m_value; auto checkExistingClass = [&] (Class* cls) { if (thisType->m_kind != KindOfObject || - !cls->name()->isame(thisType->m_value)) { + !cls->name()->isame(typeName)) { raise_error("The type %s is already defined to a different class (%s)", thisType->m_name->data(), cls->name()->data()); @@ -655,7 +656,7 @@ void Unit::defTypedef(Id id) { Typedef* td = current.asTypedef(); assert(td); if (thisType->m_kind != td->m_kind || - !td->m_value->isame(thisType->m_value)) { + !td->m_value->isame(typeName)) { raise_error("The type %s is already defined to an incompatible type", thisType->m_name->data()); } @@ -688,19 +689,28 @@ void Unit::defTypedef(Id id) { nameList->setCachedNameDef(NameDef(thisType)); return; } - if (auto klass = Unit::loadClass(thisType->m_value)) { + if (auto klass = Unit::loadClass(typeName)) { nameList->setCachedNameDef(NameDef(klass)); return; } - auto targetNameList = GetNamedEntity(thisType->m_value); + auto targetNameList = GetNamedEntity(typeName); NameDef target = targetNameList->getCachedNameDef(); if (!target) { - AutoloadHandler::s_instance->autoloadType(thisType->m_value->data()); - target = targetNameList->getCachedNameDef(); + String normName = normalizeNS(typeName); + if (normName) { + typeName = normName.get(); + targetNameList = GetNamedEntity(typeName); + target = targetNameList->getCachedNameDef(); + } + if (!target) { - raise_error("Unknown type or class %s", thisType->m_value->data()); - return; + AutoloadHandler::s_instance->autoloadType(typeName->data()); + target = targetNameList->getCachedNameDef(); + if (!target) { + raise_error("Unknown type or class %s", typeName->data()); + return; + } } } assert(target); @@ -734,6 +744,16 @@ Class* Unit::loadClass(const NamedEntity* ne, return cls; } VMRegAnchor _; + + String normName = normalizeNS(name); + if (normName) { + name = normName.get(); + ne = GetNamedEntity(name); + if ((cls = ne->getCachedClass()) != nullptr) { + return cls; + } + } + AutoloadHandler::s_instance->invokeHandler( StrNR(const_cast(name))); return Unit::lookupClass(ne); @@ -749,8 +769,20 @@ Class* Unit::loadMissingClass(const NamedEntity* ne, Class* Unit::getClass(const NamedEntity* ne, const StringData *name, bool tryAutoload) { Class *cls = lookupClass(ne); - if (UNLIKELY(!cls && tryAutoload)) { - return loadMissingClass(ne, name); + if (UNLIKELY(!cls)) { + + String normName = normalizeNS(name); + if (normName) { + name = normName.get(); + ne = GetNamedEntity(name); + if ((cls = lookupClass(ne)) != nullptr) { + return cls; + } + } + + if (tryAutoload) { + return loadMissingClass(ne, name); + } } return cls; } @@ -910,6 +942,14 @@ TypedValue* Unit::lookupPersistentCns(const StringData* cnsName) { TypedValue* Unit::loadCns(const StringData* cnsName) { TypedValue* tv = lookupCns(cnsName); if (LIKELY(tv != nullptr)) return tv; + + String normName = normalizeNS(cnsName); + if (normName) { + cnsName = normName.get(); + tv = lookupCns(cnsName); + if (tv != nullptr) return tv; + } + if (!AutoloadHandler::s_instance->autoloadConstant( const_cast(cnsName))) { return nullptr; @@ -1598,11 +1638,19 @@ Func* Unit::lookupFunc(const StringData* funcName) { Func* Unit::loadFunc(const NamedEntity* ne, const StringData* funcName) { Func* func = ne->getCachedFunc(); - if (UNLIKELY(!func)) { - if (AutoloadHandler::s_instance->autoloadFunc( - const_cast(funcName))) { - func = ne->getCachedFunc(); - } + if (LIKELY(func != nullptr)) return func; + + String normName = normalizeNS(funcName); + if (normName) { + funcName = normName.get(); + ne = GetNamedEntity(funcName); + func = ne->getCachedFunc(); + if (func) return func; + } + + if (AutoloadHandler::s_instance->autoloadFunc( + const_cast(funcName))) { + func = ne->getCachedFunc(); } return func; } diff --git a/hphp/runtime/vm/unit.h b/hphp/runtime/vm/unit.h index ff6326ebd..99a396e17 100644 --- a/hphp/runtime/vm/unit.h +++ b/hphp/runtime/vm/unit.h @@ -1092,5 +1092,17 @@ public: Class* popFront(); }; - } // HPHP::VM +/** + * If name starts with '\\', returns a new String with the leading + * slash stripped. Otherwise returns a null string. + */ +inline const String normalizeNS(const StringData* name) { + assert(name->data()[name->size()] == 0); + if (name->data()[0] == '\\') { + return String(name->data() + 1); + } + return null_string; +} + +} #endif diff --git a/hphp/test/quick/ns_invalid_class.php b/hphp/test/quick/ns_invalid_class.php new file mode 100644 index 000000000..c654f9a33 --- /dev/null +++ b/hphp/test/quick/ns_invalid_class.php @@ -0,0 +1,4 @@ +