From f3e32d83660b794410180eeec685a731db49e6c3 Mon Sep 17 00:00:00 2001 From: Jakub Vrana Date: Wed, 5 Jun 2013 14:38:15 -0700 Subject: [PATCH] Find classes used in call_user_func() Summary: Also fix false positive for call_user_func('C::f'). Also fix false positive for call_user_func("$f"). Also centralize handling of magic classes. Test Plan: call_user_func("$f"); call_user_func('C::f'); call_user_func(array('C', 'f')); call_user_func(array(1 => 'f', 0 => 'C')); Linted Phabricator. Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Differential Revision: https://secure.phabricator.com/D6137 --- scripts/lib/PhutilLibraryMapBuilder.php | 2 +- scripts/phutil_symbols.php | 42 +++++++++++++------------ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/scripts/lib/PhutilLibraryMapBuilder.php b/scripts/lib/PhutilLibraryMapBuilder.php index 9dc35ac0..dace26a3 100755 --- a/scripts/lib/PhutilLibraryMapBuilder.php +++ b/scripts/lib/PhutilLibraryMapBuilder.php @@ -21,7 +21,7 @@ final class PhutilLibraryMapBuilder { const LIBRARY_MAP_VERSION = 2; const SYMBOL_CACHE_VERSION_KEY = '__symbol_cache_version__'; - const SYMBOL_CACHE_VERSION = 9; + const SYMBOL_CACHE_VERSION = 10; /* -( Mapping libphutil Libraries )---------------------------------------- */ diff --git a/scripts/phutil_symbols.php b/scripts/phutil_symbols.php index 6dc693ef..72f0b53b 100755 --- a/scripts/phutil_symbols.php +++ b/scripts/phutil_symbols.php @@ -141,12 +141,13 @@ foreach ($functions as $function) { // Find functions used by this file. Uses: // -// - Explicit Call -// - String literal passed to call_user_func() or call_user_func_array() +// - Explicit Call +// - String literal passed to call_user_func() or call_user_func_array() +// - String literal in array literal in call_user_func()/call_user_func_array() // // TODO: Possibly support these: // -// - String literal in ReflectionFunction(). +// - String literal in ReflectionFunction(). // This is "f();". $calls = $root->selectDescendantsOfType('n_FUNCTION_CALL'); @@ -170,10 +171,22 @@ foreach ($calls as $call) { continue; } $symbol = array_shift($params); + $type = 'function'; $symbol_value = $symbol->getStringLiteralValue(); - if ($symbol_value) { + $pos = strpos($symbol_value, '::'); + if ($pos) { + $type = 'class'; + $symbol_value = substr($symbol_value, 0, $pos); + } else if ($symbol->getTypeName() == 'n_ARRAY_LITERAL') { + try { + $type = 'class'; + $symbol_value = idx($symbol->evalStatic(), 0); + } catch (Exception $ex) { + } + } + if ($symbol_value && strpos($symbol_value, '$') === false) { $need[] = array( - 'type' => 'function', + 'type' => $type, 'name' => $symbol_value, 'symbol' => $symbol, ); @@ -218,7 +231,6 @@ foreach ($classes as $class) { // - instanceof // - catch // - String literal in ReflectionClass(). -// - String literal in array literal in call_user_func()/call_user_func_array() // This is "class X ... { ... }". @@ -237,12 +249,6 @@ foreach ($classes as $class) { } } -$magic_names = array( - 'static' => true, - 'parent' => true, - 'self' => true, -); - // This is "new X()". $uses_of_new = $root->selectDescendantsOfType('n_NEW'); foreach ($uses_of_new as $new_operator) { @@ -251,10 +257,6 @@ foreach ($uses_of_new as $new_operator) { $name->getTypeName() == 'n_VARIABLE_VARIABLE') { continue; } - $name_concrete = strtolower($name->getConcreteString()); - if (isset($magic_names[$name_concrete])) { - continue; - } $need[] = array( 'type' => 'class', 'symbol' => $name, @@ -268,10 +270,6 @@ foreach ($static_uses as $static_use) { if ($name->getTypeName() != 'n_CLASS_NAME') { continue; } - $name_concrete = strtolower($name->getConcreteString()); - if (isset($magic_names[$name_concrete])) { - continue; - } $need[] = array( 'type' => 'class/interface', 'symbol' => $name, @@ -434,6 +432,10 @@ function phutil_symbols_get_builtins() { return array( 'class' => array_fill_keys($builtin['classes'], true) + array( + 'static' => true, + 'parent' => true, + 'self' => true, + 'PhutilBootloader' => true, ), 'function' => array_filter(