Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 3.7.2

Bug #13922 crash in case of malformed (but tokenized) php file
Submitted: 2008-05-17 00:31 UTC
From: gggeek Assigned: squiz
Status: Closed Package: PHP_CodeSniffer (version 1.1.0RC1)
PHP Version: 5.2.6 OS: windows xp
Roadmaps: 1.1.0    
Subscription  


 [2008-05-17 00:31 UTC] gggeek (Gaetano Giunta)
Description: ------------ ClassDeclaration.sniff raises a php exception when parsing an incomplete class that contains at least a method. The php tokrnizer otoh has no problems with it. IIRC it is valid php to have class declarations spanning multiple files... Suggestions: - do not rely on presence of $tokens[$stackPtr]['scope_opener'] in ClassDeclarationSniff::process in PEAR standards - add a new test for class well-formedness in the General series of tests Test script: --------------- <?php class myClass { function _connect() { } ?> Actual result: -------------- *** START SCOPE MAP *** Start scope map at 1: T_CLASS => class Process token 2 []: T_WHITESPACE => Process token 3 []: T_STRING => myClass Process token 4 []: T_WHITESPACE => \n Process token 5 []: T_OPEN_CURLY_BRACKET => { => Found scope opener for 1 (T_CLASS) Process token 6 [opener:5;]: T_WHITESPACE => \n Process token 7 [opener:5;]: T_WHITESPACE => Process token 8 [opener:5;]: T_FUNCTION => function * token is an opening condition * * searching for opener * Process token 9 []: T_WHITESPACE => Process token 10 []: T_STRING => _connect Process token 11 []: T_OPEN_PARENTHESIS => ( * skipping parenthesis * Process token 13 []: T_WHITESPACE => \n Process token 14 []: T_WHITESPACE => Process token 15 []: T_OPEN_CURLY_BRACKET => { => Found scope opener for 8 (T_FUNCTION) Process token 16 [opener:15;]: T_WHITESPACE => \n Process token 17 [opener:15;]: T_WHITESPACE => Process token 18 [opener:15;]: T_CLOSE_CURLY_BRACKET => } => Found scope closer for 8 (T_FUNCTION) Process token 19 [opener:5;]: T_WHITESPACE => \n Process token 20 [opener:5;]: T_CLOSE_TAG => ?> Start scope map at 8: T_FUNCTION => function Process token 9 []: T_WHITESPACE => Process token 10 []: T_STRING => _connect Process token 11 []: T_OPEN_PARENTHESIS => ( * skipping parenthesis * Process token 13 []: T_WHITESPACE => \n Process token 14 []: T_WHITESPACE => Process token 15 []: T_OPEN_CURLY_BRACKET => { => Found scope opener for 8 (T_FUNCTION) Process token 16 [opener:15;]: T_WHITESPACE => \n Process token 17 [opener:15;]: T_WHITESPACE => Process token 18 [opener:15;]: T_CLOSE_CURLY_BRACKET => } => Found scope closer for 8 (T_FUNCTION) *** END SCOPE MAP *** *** START LEVEL MAP *** Process token 0 on line 1 [lvl:0;]: T_OPEN_TAG => <?php\n Process token 1 on line 2 [lvl:0;]: T_CLASS => class Process token 2 on line 2 [lvl:0;]: T_WHITESPACE => Process token 3 on line 2 [lvl:0;]: T_STRING => myClass Process token 4 on line 2 [lvl:0;]: T_WHITESPACE => \n Process token 5 on line 3 [lvl:0;]: T_OPEN_CURLY_BRACKET => { Process token 6 on line 3 [lvl:0;]: T_WHITESPACE => \n Process token 7 on line 4 [lvl:0;]: T_WHITESPACE => Process token 8 on line 4 [lvl:0;]: T_FUNCTION => function Process token 9 on line 4 [lvl:0;]: T_WHITESPACE => Process token 10 on line 4 [lvl:0;]: T_STRING => _connect Process token 11 on line 4 [lvl:0;]: T_OPEN_PARENTHESIS => ( Process token 12 on line 4 [lvl:0;]: T_CLOSE_PARENTHESIS => ) Process token 13 on line 4 [lvl:0;]: T_WHITESPACE => \n Process token 14 on line 5 [lvl:0;]: T_WHITESPACE => Process token 15 on line 5 [lvl:0;]: T_OPEN_CURLY_BRACKET => { => Found scope opener for 8 (T_FUNCTION) * level increased * * token 8 (T_FUNCTION) added to conditions array * Process token 16 on line 5 [lvl:1;conds;T_FUNCTION;]: T_WHITESPA CE => \n Process token 17 on line 6 [lvl:1;conds;T_FUNCTION;]: T_WHITESPA CE => Process token 18 on line 6 [lvl:1;conds;T_FUNCTION;]: T_CLOSE_CU RLY_BRACKET => } => Found scope closer for 15 (T_OPEN_CURLY_BRACKET) * token T_FUNCTION removed from conditions array * * level decreased * Process token 19 on line 6 [lvl:0;]: T_WHITESPACE => \n Process token 20 on line 7 [lvl:0;]: T_CLOSE_TAG => ?> *** END LEVEL MAP *** [21 tokens in 7 lines]... Notice: Undefined index: scope_opener in D:\htdocs\PHP_CodeSniffer\CodeSniffer\ Standards\PEAR\Sniffs\Classes\ClassDeclarationSniff.php on line 63 Call Stack: 0.0004 56528 1. {main}() D:\htdocs\PHP_CodeSniffer\scripts\phpcs:0 0.0201 1133720 2. PHP_CodeSniffer_CLI->process() D:\htdocs\PHP_CodeSniffer\scripts\phpcs:30 0.0228 1137688 3. PHP_CodeSniffer->process() D:\htdocs\PHP_CodeSniffer\CodeSniffer\CLI.php:334 0.1260 2619240 4. PHP_CodeSniffer->processFile() D:\htdocs\PHP_CodeSniffer\CodeSniffer.php:278 0.1337 2671040 5. PHP_CodeSniffer_File->start() D:\htdocs\PHP_CodeSniffer\CodeSniffer.php:600 0.2548 2756496 6. PEAR_Sniffs_Classes_ClassDeclarationSniff->process() D:\htdocs\PHP_CodeSniffer\CodeSniffer\File.php:378 Notice: Undefined index: in D:\htdocs\PHP_CodeSniffer\CodeSniffer\Standards\PEAR\Sniffs\Classes\ClassDeclarationSniff.php on line 66 Call Stack: 0.0004 56528 1. {main}() D:\htdocs\PHP_CodeSniffer\scripts\phpcs:0 0.0201 1133720 2. PHP_CodeSniffer_CLI->process() D:\htdocs\PHP_CodeSniffer\scripts\phpcs:30 0.0228 1137688 3. PHP_CodeSniffer->process() D:\htdocs\PHP_CodeSniffer\CodeSniffer\CLI.php:334 0.1260 2619240 4. PHP_CodeSniffer->processFile() D:\htdocs\PHP_CodeSniffer\CodeSniffer.php:278 0.1337 2671040 5. PHP_CodeSniffer_File->start() D:\htdocs\PHP_CodeSniffer\CodeSniffer.php:600 0.2548 2756496 6. PEAR_Sniffs_Classes_ClassDeclarationSniff->process() D:\htdocs\PHP_CodeSniffer\CodeSniffer\File.php:378 Fatal error: Uncaught PHP_CodeSniffer_Exception: $stackPtr cannot be null in D:\ htdocs\PHP_CodeSniffer\CodeSniffer\Standards\PEAR\Sniffs\Classes\ClassDeclaratio nSniff.php on line 88 #0 D:\htdocs\PHP_CodeSniffer\CodeSniffer\Standards\PEAR\Sniffs\Classes\ClassDecl arationSniff.php(88): PHP_CodeSniffer_File->addError('Opening class b...', NULL) #1 D:\htdocs\PHP_CodeSniffer\CodeSniffer\File.php(378): PEAR_Sniffs_Classes_ClassDeclarationSniff->process(Object(PHP_CodeSniffer_File), 1) #2 D:\htdocs\PHP_CodeSniffer\CodeSniffer.php(600): PHP_CodeSniffer_File->start(NULL) #3 D:\htdocs\PHP_CodeSniffer\CodeSniffer.php(278): PHP_CodeSniffer->processFile('D:\htdocs\ezp\s...') #4 D:\htdocs\PHP_CodeSniffer\CodeSniffer\CLI.php(334): PHP_CodeSniffer->process(Array, 'PEAR', Array, false) #5 D:\htdocs\PHP_CodeSniffer\scripts\phpcs(30): PHP_CodeSniffer_CLI->process() #6 {main} thrown in D:\htdocs\PHP_CodeSniffer\CodeSniffer\File.php on line 506

Comments

 [2008-05-18 10:44 UTC] squiz (Greg Sherwood)
I'm not sure about the splitting classes comment. The OOP page of the PHP manual (http://www.php.net/oop) states: "You can NOT break up a class definition into multiple files." in a big warning box no less. Also, while the code tokenises it also causes a parse error, so it is not valid. PHP will tokenise pretty much anything as long as you start it with a PHP tag. In previous cases like this, I've added a warning to the line that states that there may be a parse error, and I'll do the same thing in this case.
 [2008-05-18 10:58 UTC] gggeek (Gaetano Giunta)
Uhm, I should go back to reading my php fundamentals, then... Anyway, a warning is fine - as long as the exception is caught: as you have correctly stated the parsed code is invalid. The only problem with the current situation is that a crash of the script in case of invalid php code prevents parsing of huge dirs where there might be some stupid leftover code bits.
 [2008-05-18 11:20 UTC] squiz (Greg Sherwood)
"The only problem with the current situation is that a crash of the script in case of invalid php code prevents parsing of huge dirs where there might be some stupid leftover code bits." I agree 100%.
 [2008-05-19 05:59 UTC] squiz (Greg Sherwood)
This bug has been fixed in CVS. If this was a documentation problem, the fix will appear on pear.php.net by the end of next Sunday (CET). If this was a problem with the pear.php.net website, the change should be live shortly. Otherwise, the fix will appear in the package's next release. Thank you for the report and for helping us make PEAR better.