Fix use-after-free bug in RPC handler
[hiphop-php.git] / hphp / compiler / expression / static_class_name.cpp
blob0f2c08e7012ad1019086d105a33d1c1c90e99417
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/compiler/expression/static_class_name.h"
18 #include "hphp/compiler/expression/scalar_expression.h"
19 #include "hphp/compiler/expression/simple_variable.h"
20 #include "hphp/compiler/statement/statement_list.h"
21 #include "hphp/compiler/analysis/class_scope.h"
22 #include "hphp/compiler/analysis/file_scope.h"
23 #include "hphp/compiler/analysis/variable_table.h"
24 #include "hphp/util/text-util.h"
26 namespace HPHP {
27 ///////////////////////////////////////////////////////////////////////////////
29 StaticClassName::StaticClassName(ExpressionPtr classExp)
30 : m_class(classExp),
31 m_self(false), m_parent(false), m_static(false),
32 m_redeclared(false), m_present(false), m_unknown(true) {
33 updateClassName();
34 auto const isame = [](const std::string& a, const std::string& b) {
35 return (a.size() == b.size()) &&
36 !strncasecmp(a.c_str(), b.c_str(), a.size());
38 if (isame(m_origClassName, "parent")) {
39 m_parent = true;
40 } else if (isame(m_origClassName, "self")) {
41 m_self = true;
42 } else if (isame(m_origClassName, "static")) {
43 m_static = true;
44 m_present = true;
45 m_class = classExp;
46 m_origClassName = "";
50 void StaticClassName::onParse(AnalysisResultConstPtr ar, FileScopePtr scope) {
51 if (!m_self && !m_parent && !m_static && hasStaticClass()) {
52 ar->parseOnDemandByClass(m_origClassName);
56 bool StaticClassName::isNamed(folly::StringPiece clsName) const {
57 return bstrcasecmp(m_origClassName, clsName) == 0;
60 void StaticClassName::updateClassName() {
61 if (m_class && m_class->is(Expression::KindOfScalarExpression) &&
62 !m_static) {
63 auto s = dynamic_pointer_cast<ScalarExpression>(m_class);
64 auto const& className = s->getString();
65 m_origClassName = className;
66 m_class.reset();
67 } else {
68 m_origClassName = "";
72 ClassScopePtr StaticClassName::resolveClass() {
73 m_present = false;
74 m_unknown = true;
75 if (m_class) return ClassScopePtr();
76 auto scope = dynamic_cast<Construct*>(this)->getScope();
77 if (m_self) {
78 if (ClassScopePtr self = scope->getContainingClass()) {
79 m_origClassName = self->getOriginalName();
80 m_present = true;
81 m_unknown = false;
82 return self;
84 } else if (m_parent) {
85 if (ClassScopePtr self = scope->getContainingClass()) {
86 if (!self->getOriginalParent().empty()) {
87 m_origClassName = self->getOriginalParent();
88 m_present = true;
90 } else {
91 m_parent = false;
94 ClassScopePtr cls = scope->getContainingProgram()->findClass(m_origClassName);
95 if (cls) {
96 m_unknown = false;
97 if (cls->isVolatile()) {
98 ClassScopeRawPtr c = scope->getContainingClass();
99 if (c && c->isNamed(m_origClassName)) {
100 c.reset();
102 m_present = c.get() != nullptr;
103 if (cls->isRedeclaring()) {
104 cls = c;
105 if (!m_present) m_redeclared = true;
107 } else {
108 m_present = true;
111 return cls;
114 ///////////////////////////////////////////////////////////////////////////////
116 void StaticClassName::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
117 if (m_class) {
118 m_class->outputPHP(cg, ar);
119 } else {
120 cg_printf("%s", m_origClassName.c_str());
124 ///////////////////////////////////////////////////////////////////////////////