$token) { if (is_string($token)) { if ($token === '{') $depth++; else if ($token === '}') $depth--; continue; } if ($depth !== 0) continue; list($id, $text, $line) = array($token[0], $token[1], $token[2]); if (in_array($id, $controlFlow, true)) { $found[] = "$line: $text"; continue; } // A bare function call at file scope, e.g. `zm_authenticate_request();`. // The name in a `function foo(` / `class Foo` declaration is also a T_STRING // followed by '(', so look back and skip declarations. if ($id === T_STRING and !in_array(strtolower($text), $allowedCalls, true)) { $declaration = false; for ($j = $i - 1; $j >= 0; $j--) { $prev = $tokens[$j]; if (is_array($prev) and $prev[0] === T_WHITESPACE) continue; $declaration = is_array($prev) and in_array($prev[0], array(T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT, T_CONST), true); break; } if ($declaration) continue; for ($j = $i + 1; $j < count($tokens); $j++) { $next = $tokens[$j]; if (is_array($next) and $next[0] === T_WHITESPACE) continue; if ($next === '(') $found[] = "$line: $text("; break; } } } return $found; } $authPath = __DIR__.'/../../web/includes/auth.php'; check('auth.php executes nothing at include time', topLevelExecutableStatements($authPath), array()); // The extracted work must still exist, or the above would pass vacuously. $source = file_get_contents($authPath); check('zm_authenticate_request() is defined', (bool)preg_match('/^function zm_authenticate_request\(\)/m', $source), true); // Sanity-check the detector itself against a file that does run code on // include, so a broken checker cannot silently report success above. $fixture = tempnam(sys_get_temp_dir(), 'zmtest').'.php'; file_put_contents($fixture, "