Carnet Wiki

Analyse statique à partir de phpstan

Version 11 — il y a 1 mois JLuc

Voir bootstrap, framework, sdk

#!/usr/bin/env bash

# Dans SPIP lui-même, les appels de fonctions non trouvées par phpstan
grep "Function " phpstan-baseline.neon | grep 'not found' \
    | sed -e 's/.*Function //' -e 's/ not found.*//' >> tmp/spip_called.txt
cat tmp/spip_called.txt 
# cache_unlock
# analyser_backend
# image_du_document
# vignette_automatique

# Récupération de la liste des baselines
find plugins-dist/spip -name phpstan-baseline.neon \
    | grep -v vendor > tmp/baselines.txt

# Récupération de la liste des fonctions non trouvées par phpstan
rm -f tmp/_called.txt tmp/called.txt
while read -r baseline
do
    grep "Function " "$baseline" | grep 'not found' \
        | sed -e 's/.*Function //' -e 's/ not found.*//' >> tmp/_called.txt
done < tmp/baselines.txt
wc -l tmp/_called.txt
# 2052 tmp/_called.txt
rm -f tmp/baselines.txt
sort tmp/_called.txt | uniq > tmp/called.txt
rm -f tmp/_called.txt
wc -l tmp/called.txt
# 330 tmp/called.txt

# Trouver les fichiers spip déclarant ces fonctions
rm -f tmp/_files.txt tmp/files.txt
while read -r fonction
do
    grep -E -rn --exclude-dir tests "^function $fonction\(" ecrire \
        | cut -d: -f1 >> tmp/_files.txt
done < tmp/called.txt
sort tmp/_files.txt | uniq > tmp/files.txt
rm -f tmp/_files.txt
wc -l tmp/files.txt
# 64 tmp/files.txt

rm -f tmp/spip_files_functions.txt
while read -r fichier
do
    grep -E '^function (.*)\(' "$fichier" | sed -e 's/function //' -e 's/(.*//' | while read -r f
    do
        echo "$fichier,$f" >> tmp/spip_files_functions.txt
    done
done < tmp/files.txt
wc -l tmp/spip_files_functions.txt
# 1244 tmp/spip_files_functions.txt

echo "ecrire/inc/utils.php
ecrire/base/connect_sql.php
ecrire/base/objets.php
ecrire/inc/flock.php" > tmp/bootstrap.txt
rm -f tmp/bootstrap_files_functions.txt
while read -r fichier
do
    grep -E '^function (.*)\(' "$fichier" | sed -e 's/function //' -e 's/(.*//' | while read -r f
    do
        echo "$fichier,$f" >> tmp/bootstrap_files_functions.txt
    done
done < tmp/bootstrap.txt
wc -l tmp/bootstrap_files_functions.txt
# 135 tmp/bootstrap_files_functions.txt

rm -f tmp/non_called_bootstrap.txt
while read -r f
do
    fonction=$(cut -d, -f2 <<< "$f")
    if ! grep -E -c "^${fonction}$" tmp/called.txt > /dev/null
    then
        echo "$fonction" >> tmp/non_called_bootstrap.txt
    fi
done < tmp/bootstrap_files_functions.txt
wc -l tmp/non_called_bootstrap.txt
Fichiers
Liste des fichiers contenant au moins une fonction appelée par un plugin dist
Fonctions
Liste des fonctions appelées au moins une fois dans du code php des plugins dist

Séquence de démarrage de SPIP

Le design pattern du front controller est lié à la conception d’applications Web. Il s’agit d’un « contrôleur qui gère toutes les demandes/requêtes d’un site Web ». SPIP dispose de 2 front controllers : spip.php et ecrire/index.php. Ce sont les points d’entrée pour les requêtes HTTP. On peut aller jusqu’à considérer que SPIP est un ensemble de 2 applications Web solidaires, indissociables.

grep -En "(include|require)(_once)?( |\()" spip.php
# 17:include_once _DIR_RESTREINT_ABS.'inc_version.php';
# 20:include _DIR_RESTREINT_ABS.'public.php';
grep -En "(include|require)(_once)?( |\()" ecrire/index.php
# 21:     include __DIR__ . '/inc_version.php';

Les scripts web spip.php et ecrire/index.php exécutent de manière inconditionnelle le fichier ecrire/inc_version.php. C’est, de manière interne, le véritable point d’entrée de la séquence de démarrage d’une requête HTTP. Il peut être utilisé pour des scripts en ligne de commande (CLI)

Celui-ci va charger d’autres fichiers PHP :

grep -En "(include|require)(_once)?( |\()" ecrire/inc_version.php
# 84:     include $f;
# 88:require_once __DIR__ . '/../vendor/autoload.php';
# 473:require_once _ROOT_RESTREINT . 'inc/utils.php';
# 474:require_once _ROOT_RESTREINT . 'base/connect_sql.php';
# 479:    include_once _FILE_OPTIONS;
# 512:    include_once(_CACHE_PLUGINS_OPT);

Ligne 84, s’il existe, l’écran de sécurité (par défaut config/ecran_securite.php).
Ligne 88, l’autoloader de composer.
Ligne 473 : le fichier ecrire/inc/utils.php (celui-ci initialise 2 globales et déclare des fonctions).
Ligne 474 : le fichier ecrire/base/connect_sql.php.
Ligne 479 : le fichier config/mes_options.php s’il existe.
Ligne 512 : le fichier tmp/cache/charger_plugins_options.php s’il existe, sinon une suite d’appels (voir plus bas).

grep -En "(include|require)(_once)?( |\()" ecrire/inc/utils.php
# 125:            include_once $file;
# 195:                    include_once(_ROOT_CWD . $f);
# 200:                    include_once(_CACHE_PLUGINS_FCT);
# 295:                    include_once $charger;
# 1609:                   include_once _ROOT_CWD . $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file];
# 1629:                                   include_once _ROOT_CWD . $a;
# 1677:           include_once(_CACHE_PLUGINS_PATH);
# 1736:           include_once _ROOT_RESTREINT . 'inc/flock.php';
# 2659:           include_once _FILE_CHMOD;
# 2715:   include_once _ROOT_RESTREINT . 'inc/flock.php';

Ligne 125 : le fichier $file in include_once_check($file)
Ligne 195 : le fichier squelettes/mes_fonctions.php s’il existe, in include_fichiers_fonctions()
Ligne 200 : le fichier tmp/cache/charger_plugins_fonctions.php s’il existe, in include_fichiers_fonctions()
Ligne 295 : le fichier tmp/cache/charger_pipelines.php s’il existe, in pipeline($action, $val = null)
Ligne 1609 : ???/$dirname/$file in find_in_path($file, $dirname = ’’, $include = false) si $include vaut true.
Ligne 1629 : ???/$dirname/$file in find_in_path($file, $dirname = ’’, $include = false) si $include vaut true.
Ligne 1677 : le fichier tmp/cache/charger_plugins_chemins.php s’il existe, in load_path_cache().
Ligne 1736 : le fichier ecrire/inc/flock.php in find_all_in_path($dir, $pattern, $recurs = false).
Ligne 2659 : le fichier config/chmod.php in spip_initialisation_core($pi = null, $pa = null, $ti = null, $ta = null).
Ligne 2715 : le fichier ecrire/inc/flock.php in spip_initialisation_core($pi = null, $pa = null, $ti = null, $ta = null).

grep -En "(include|require)(_once)?( |\()" config/chmod.php
#
grep -En "(include|require)(_once)?( |\()" ecrire/inc/flock.php
#
grep -En "(include|require)(_once)?( |\()" ecrire/base/connect_sql.php
# 20:require_once _ROOT_RESTREINT . 'base/objets.php';
# 86:                     include($f);

Ligne 20 : Le fichier ecrire/base/objets.php.
Ligne 86 : Le fichier config/connect.php in spip_connect($serveur = ’’, $version = ’’). Cas particulier, ça peut être config/connect.tmp.php pendant une phase d’installation.

grep -En "(include|require)(_once)?( |\()" ecrire/base/objets.php
# 
grep -En "(include|require)(_once)?( |\()" ecrire/public.php 
# 34:                     include_once _ROOT_RESTREINT . 'inc_version.php';
# 151:    include _ROOT_RESTREINT . 'public/evaluer_page.php';