Conditional Code Analysis

Conditional Code Analysis – improve accuracy detection with conditional code

Categories

As briefly introduced at end of advanced detection chapter, we will learn now that there are 3 categories of conditional code that could give wrong result, if there are not catched properly.

These categories are :

  • function (cond_code = 1)

    A quick example:

    <?php
    if (function_exists('debug_backtrace')) {
        
    $backtrace debug_backtrace();
    } else {
        
    $backtrace false;
    }
    ?>
  • extension (cond_code = 2)

    A quick example:

    <?php
    if (extension_loaded('sqlite') == false) {
        
    $prefix = (PHP_SHLIB_SUFFIX === 'dll') ? 'php_' '';
        
    dl($prefix 'sqlite.' PHP_SHLIB_SUFFIX);
        echo 
    'SQLite version : ' sqlite_libversion();
    }
    ?>
  • constant (cond_code = 4)

    A quick example:

    <?php
    if (defined('DATE_RSS') {
        
    $date_format DATE_RSS;
    } else {
        
    $date_format 'D, j M Y H:i:s O';
    }
    // will display something like "Sat, 26 Jul 2008 16:56:24 +0200"
    echo date($date_formatmktime(0007262008));
    ?>

How to catch them with web interface

At the beginning of first version that catch conditional code, there were only 3 options: ignore_functions, ignore_extensions and ignore_constants.

Incovenient with these options, is that you should know the source code to parse, and identify whose functions, extensions or constants to avoid.

Version 1.7.0 of API has introduced the ability to add name patterns to identify all or part of functions, extensions, constants to ignore from parsing. You should use now these options: ignore_functions_match, ignore_extensions_match or ignore_constants_match.

Let's take a look with an example, how it's easy to catch whatever you want to exclude from parsing. We will take again example of PEAR::HTML_CSS 1.5.1 package already seen in advanced directory detection .

<?php
require_once 'PHP/CompatInfo.php';

$datasource '/tmp/HTML_CSS-1.5.1';
$options    = array(
    
'ignore_dirs' => array('examples''tests'),
    
'ignore_functions_match' => array('function_exists', array('/.*/')),
    
'ignore_extensions_match' => array('extension_loaded', array('/.*/')),
    
'ignore_constants_match' => array('defined', array('/.*/')),
    );

$pci = new PHP_CompatInfo();
$pci->parseData($datasource$options);
?>

Here we catch all standard conditional code (function_exists, extension_loaded, defined) what match all names (regular expression given by array('/.*/')).

To catch what ever function you want, use preg_match rather than function_exists.

It's also true for extension_loaded and defined

With preg_match you are really free to ignore a single function, a group set or all functions, only by giving the good name pattern.

Example to ignore all functions prefixed by xdebug_ :

<?php
require_once 'PHP/CompatInfo.php';

$datasource '/tmp/HTML_CSS-1.5.1';
$options    = array(
    
'ignore_functions_match' => array('preg_match', array('/^xdebug_/')),
    );

$pci = new PHP_CompatInfo();
$pci->parseData($datasource$options);
?>

How to catch them with CLI

If you use the command-line parser with pci script, the solution is a bit different.

To catch cond_code = 1 (function), you must run the command pci -inm functions-match.txt where functions-match.txt is a text file, that identify on each line a new condition.

Each blank line or beginning with ; will be skipped (proceed as comment line like in php.ini)

If first non blank character is an equal sign (=), then you can catch what ever function you want with a preg_match condition (see xdebug example in previous section (web interface)

Example of text file contents

;=^xdebug_
;=alias$
.*
;file_put_contents
    

Do not confuse a regular expression beginning with equal sign (=), and the same line without =.

In first case you will catch all functions that match the name pattern given found in all source code, while second case try to catch only matches found with if function_exists('') condition.

It's also true for extensions and constants, we will see them now.

To catch cond_code = 2 (extension), you must run the command pci -iem extensions-match.txt where extensions-match.txt is a text file, that identify on each line a new condition.

Each blank line or beginning with ; will be skipped (proceed as comment line like in php.ini)

If first non blank character is an equal sign (=), then you can catch what ever extension you want with a preg_match condition.

Example of text file contents

;=xdebug
;sqlite
=gd
;=sapi_apache
    

To catch cond_code = 4 (constant), you must run the command pci -icm constants-match.txt where constants-match.txt is a text file, that identify on each line a new condition.

Each blank line or beginning with ; will be skipped (proceed as comment line like in php.ini)

If first non blank character is an equal sign (=), then you can catch what ever constant you want with a preg_match condition.

Example of text file contents

=PHP_EOL
=DATE_RSS
;FILE_FIND_VERSION