Как перехватить использование оператора обратной кавычки PHP через PHP_CodeSniffer?

Я изучил некоторые «нюхки» из стандартов кодирования «Generic» и «Squiz», которые поставляются с CodeSniffer версии 1.3., и научился достаточно, чтобы написать несколько "нестандартных" сниффов, чтобы поймать некоторые антишаблоны кодирования, характерные для проекта PHP, над которым я работаю.

Но теперь мой босс хочет, чтобы я использовал этот инструмент, чтобы определить все места, где код вызывает exec(), popen(), passthru() или использует оператор обратной кавычки для запуска «внешней» команды, и я наткнулся на загвоздка, связанная с обратными кавычками.

Класс Generic_Sniffs_PHP_ForbiddenFunctionsSniff, поставляемый с дистрибутивом CodeSniffer 1.3, существенно упрощает идентификацию любых вызовов «опасных функций», таких как exec(), popen() и passthru(), так что эта часть проста.

Но я не вижу никаких ссылок на операторы обратной кавычки в "стандартных" сниффах, а также я не вижу никаких упоминаний об операторе обратной кавычки в какой-либо логике CodeSniffer - хотя, возможно, я ищу не в том месте (мне потребовалось некоторое время, чтобы выясните, например, что «->» на самом деле T_OBJECT_OPERATOR).

Итак, мой вопрос заключается в следующем:

Могу ли я использовать PHP_CodeSniffer для обнаружения использования оператора обратной кавычки в коде PHP, и если да, то как?


person Peter    schedule 06.09.2011    source источник


Ответы (2)


http://php.net/manual/en/tokens.php

Похоже, нет токена для обратных кавычек. Однако вы должны быть в состоянии следовать иерархии классов достаточно низко, чтобы вы могли найти точку соединения, где вы можете просто выполнить strpos или preg_match в поисках `. В документации CodeSniffer должно быть указано, как это сделать, или, как я уже сказал, вы можете следовать классу Generic_Sniffs_PHP_ForbiddenFunctionsSniff до его родителя (и до его родителя, если необходимо), пока не обнаружите, где происходит фактический поиск.

Изменить: только что просмотрел код CodeSniffer, и оказалось, что он может поддерживать только поиск токенов... Так что похоже, вам придется создать новый токен.

person Corbin    schedule 06.09.2011
comment
Что ж, он должен быть пойман токеном необработанного символа (не именованным токеном, а строкой вместо массива внутри вывода token_get_all). Так что, если он не отфильтровывает призраков, должно быть возможно ... - person ircmaxell; 07.09.2011
comment
@Corbin: я боялся этого. Спасибо за подтверждение моих подозрений — по крайней мере, теперь я буду меньше беспокоиться о том, что трачу время впустую, когда погружаюсь в внутренности CodeSniffer. Но я немного удивлен, обнаружив пробел такого размера в существующей функциональности CodeSniffer, учитывая, насколько зрелым кажется проект. - person Peter; 07.09.2011
comment
@ircmaxell: Спасибо за совет. Я дам вам знать, как это получится. - person Peter; 07.09.2011
comment
@ircmaxell Сниффер кода регистрирует обработчики на основе обратных вызовов токена, поэтому, если токен не существует в его системе, вы не можете зарегистрировать обратный вызов. (Если нет способа зарегистрировать обратный вызов для всех файлов, но это не очень эффективно.) Если только я неправильно понял ваш совет, и вы имеете в виду, что CodeSniffer может регистрировать необработанные токены. @Peter Я очень удивлен, что его тоже нет, особенно потому, что люди могут захотеть запретить `токен, цитирующий SQL-запросы. - person Corbin; 07.09.2011
comment
@Corbin, @ircmaxell: На самом деле токен T_NONE определен, и связанный с ним атрибут содержимого можно проверить, чтобы убедиться, что он соответствует `. Этого может быть достаточно, чтобы написать нужные мне сниффы, не взламывая сам CodeSniffer. - person Peter; 07.09.2011
comment
@Corbin: к вашему сведению, токен T_BACKTICK теперь официально часть CodeSniffer . - person Peter; 29.09.2011
comment
Потрясающий! Я немного удивлен, что они не заметили этого с самого начала.... Но что бы ни работало :). - person Corbin; 30.09.2011

Этот пример (с удаленным большинством комментариев) работает с несколькими простыми тестовыми примерами — никаких изменений CodeSniffer не требуется!

class test_Sniffs_Dangerous_BackTickSniff implements PHP_CodeSniffer_Sniff {

public $supportedTokenizers = array('PHP');

public function register() {
    return array(T_NONE);
}

public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) {
    // generate one error for every pair of backticks:
    static $reported = array();

    $all_tokens = $phpcsFile->getTokens();

    if ($all_tokens[$stackPtr]['content'] == '`') {
        $lno = $all_tokens[$stackPtr]['line'];
        if (!isset($reported[$lno])) {
            $reported[$lno] = true;
            $phpcsFile->addError('Avoid backticks', $stackPtr);
        }
    }
}

}

Поскольку это то, что я искал, я собираюсь ответить на свой вопрос. Спасибо Corbin и ircmaxell за ваши комментарии.

person Peter    schedule 07.09.2011
comment
К счастью, Грег Шервуд предоставил мне запрос функции: pear.php.net/bugs /bug.php?id=18799 - person Peter; 12.09.2011