La création et l'appel dynamique de fonctions sont l'un des mécanismes les plus flexibles de Perl, hérité des traditions de LaTeX et des scripts shell. Depuis les premières versions, Perl permet d'appeler des fonctions par chaîne (via des liens symboliques/globs), de stocker des références à des sous-programmes dans des variables et des tableaux associatifs, ainsi que la construction AUTOLOAD pour générer des fonctions à la volée.
Le principal problème de cette approche est la sécurité (la possibilité d'appeler une fonction indésirable par une chaîne substituée) et la performance (la résolution symbolique des noms est plus lente que l'appel direct). Il est également important de contrôler la portée des fonctions et de transmettre le bon nombre d'arguments.
La solution consiste à utiliser un dispatcher de hachage (mapping de chaîne/clé à coderef), à éviter eval pour exécuter le code utilisateur, et à définir clairement la liste des fonctions autorisées à être appelées.
Exemple de code (dispatch par clé) :
my %dispatch = ( add => sub { $_[0] + $_[1] }, sub => sub { $_[0] - $_[1] }, mult => sub { $_[0] * $_[1] }, ); my $key = 'add'; if (exists $dispatch{$key}) { print $dispatch{$key}->(2, 3); # Affiche 5 } else { die "Action inconnue $key"; }
Caractéristiques principales :
Peut-on appeler une fonction par son nom en utilisant uniquement une chaîne ?
Réponse : Oui, mais c'est dangereux — l'appel $fn_name->() ou via un lien symbolique direct &$fn_name(); n'est pas recommandé avec des données externes (utilisateur), car cela peut conduire à des vulnérabilités potentielles.
Y a-t-il une différence entre une référence de code et le nom d'une fonction en Perl ?
Réponse : Oui, le nom de la fonction est toujours global, tandis qu'une référence de fonction (coderef) peut être lexicale, locale, transmise entre des sous-programmes et contenir une fonction anonyme.
my $coderef = sub { ... }; my $named = \&fn_name;
Que se passe-t-il si l'on appelle une fonction inexistante via un dispatcher de hachage ?
Réponse : S'il n'y a pas de clé — une erreur se produira. Une vérification de exists est donc toujours nécessaire avant l'appel et la gestion des commandes non reconnues, sinon, il y aura une tentative d'appel de undef (erreur fatale).
Une commande sur le site prend le nom d'une fonction à partir d'un paramètre GET et appelle via eval — n'importe quel utilisateur peut appeler system, unlink et d'autres fonctions dangereuses.
Avantages :
Inconvénients :
On utilise un hachage avec une liste blanche de fonctions, tous les indicateurs sont validés, eval n'est pas utilisé, les erreurs sont interceptées et enregistrées.
Avantages :
Inconvénients :