Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

petite question sur perl -w

6 réponses
Avatar
paul POULAIN
Bonjour,

Les développeurs du projet Koha ont pris de bonnes résolutions pour la
prochaine version majeure en mettant un -w pour avoir le code le plus
propre possible.

Bon, on améliore les choses, et finalement assez vite, mais je butte sur un
problème :
lorsque l'on fait :
my $variable = $cgi->param('toto') pour récupérer le contenu de la variable
toto passée par un formulaire CGI, si toto n'est pas défini, $variable est
aussi défini.
et un
if ($variable eq 'machin') met un warning du genre 'use uninitialized value
blabla'

Pour l'éviter, un my $variable = $cgi->param('toto') ||''; fonctionne,
mais :
1- est-ce propre ?
2- peut on faire autrement ?

Merci d'avance
--
Paul

6 réponses

Avatar
Jacques Caron
Salut,

On Wed, 26 Oct 2005 11:03:01 +0200, paul POULAIN
wrote:

Pour l'éviter, un my $variable = $cgi->param('toto') ||''; fonctionne,
mais :
1- est-ce propre ?


Ca dépend :-) S'il y a besoin de faire la différence entre un champ absent
et un champ vide, non, ce n'est pas propre. Aussi, "" n'est pas forcément
une bonne valeur par défaut, il peut y avoir un défaut spécifique à chaque
variable, c'est vraiment spécifique à l'application.

2- peut on faire autrement ?


A chaque fois qu'on veut utiliser $variable faire un test du type if
(defined $variable && $variable ...). C'est lourd, mais ça marche. Mais le
choix d'une valeur par défaut adaptée à chaque variable avec un || au
début est probablement la meilleure option, oui.

Jacques.
--
Oxado http://www.oxado.com/

Avatar
Paul Gaborit
À (at) Wed, 26 Oct 2005 11:03:01 +0200,
paul POULAIN écrivait (wrote):
Bon, on améliore les choses, et finalement assez vite, mais je butte sur un
problème :
lorsque l'on fait :
my $variable = $cgi->param('toto') pour récupérer le contenu de la variable
toto passée par un formulaire CGI, si toto n'est pas défini, $variable est
aussi défini.
et un
if ($variable eq 'machin') met un warning du genre 'use uninitialized value
blabla'


Il y a une grosse différence entre un champ vide et un champ non
défini. Peut-être qu'il n'y en pas dans votre application mais ce
n'est pas toujours le cas.

La "meilleure" solution me semble-t-il serait :

if (defined $variable and $variable eq 'machin') {
...
}

Ou (si une valeur par défaut *doit* exister) :

my $variable = $cgi->param('toto');
if (not defined $variable) {
$variable = "valeur par défaut";
}

La ligne suivante *ne* fonctionne *pas* comme il faut :

my $variable = $cgi->param('toto') || ''; # PAS GLOP !!!

Pour vous en convaincre, passez donc la valeur '0' (zéro) dans le
paramètre 'toto' et vous comprendrez...

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>

Avatar
paul POULAIN
Paul Gaborit wrote:
Il y a une grosse différence entre un champ vide et un champ non
défini. Peut-être qu'il n'y en pas dans votre application mais ce
n'est pas toujours le cas.
C'est tout à fait ce que je me suis dit. Et en l'occurence, dans tous les

cas que j'ai vu, il n'y a effectivement pas de différence.


La "meilleure" solution me semble-t-il serait :

if (defined $variable and $variable eq 'machin') {
...
}
un peu lourd si le test est fait de multiples fois, ce qui est souvent mon

cas.

Ou (si une valeur par défaut *doit* exister) :

my $variable = $cgi->param('toto');
if (not defined $variable) {
$variable = "valeur par défaut";
}
ca me plait plus. Un

$variable='valeur par defaut' unless defined $variable;
serait encore plus concis et identique si je ne me trompe.

La ligne suivante *ne* fonctionne *pas* comme il faut :

my $variable = $cgi->param('toto') || ''; # PAS GLOP !!!

Pour vous en convaincre, passez donc la valeur '0' (zéro) dans le
paramètre 'toto' et vous comprendrez...


Pas besoin, je sais ce que ca fait, et ca me convient, parmi les valeurs
possibles il n'y a pas de 0 ;-)
--
Paul

Avatar
Paul Gaborit
À (at) Wed, 26 Oct 2005 18:04:08 +0200,
paul POULAIN écrivait (wrote):
[...]
Ou (si une valeur par défaut *doit* exister) :

my $variable = $cgi->param('toto');
if (not defined $variable) {
$variable = "valeur par défaut";
}
ca me plait plus. Un

$variable='valeur par defaut' unless defined $variable;
serait encore plus concis et identique si je ne me trompe.


Sauf que ça me semble contraire aux guidelines d'écriture de Perl. Il
faut mettre la chose importante en premier. Or là, ce qui est
important (me semble-t-il), c'est que la variable n'est pas
définie. Donc pour que ce soit concis et conforme :

defined $variable or $variable = "valeur par défaut";

Ok... je pinaille ;-)

Par ailleurs, pour des raisons de sécurité, tout script CGI devrait
être développé avec l'option -T active. Dans ce cas, il vous faudra
écrire un bout de code permettant d'"untaint"er les valeurs récupérées
via 'param'. C'est en général dans cette partie qu'on
gère/détecte/filtre les différentes situations : si le paramètre n'est
pas définie mais aussi s'il est défini avec une valeur incohérente,
illogique ou interdite, s'il est défini plusieurs fois ou s'il est mal
encodé, etc. ce qui augmente le nombre de cas à gérer et qui empêche
la concision du test...

La ligne suivante *ne* fonctionne *pas* comme il faut :

my $variable = $cgi->param('toto') || ''; # PAS GLOP !!!

Pour vous en convaincre, passez donc la valeur '0' (zéro) dans le
paramètre 'toto' et vous comprendrez...


Pas besoin, je sais ce que ca fait, et ca me convient, parmi les valeurs
possibles il n'y a pas de 0 ;-)


Alors n'oubliez pas d'y mettre un commentaire pour ceux qui prendront
la suite sans savoir ce qu'ils font... ;-)

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>


Avatar
paul POULAIN
Paul Gaborit wrote:

Sauf que ça me semble contraire aux guidelines d'écriture de Perl. Il
faut mettre la chose importante en premier. Or là, ce qui est
important (me semble-t-il), c'est que la variable n'est pas
définie. Donc pour que ce soit concis et conforme :

defined $variable or $variable = "valeur par défaut";

Ok... je pinaille ;-)


oui, mais justement, puisqu'on essaye de faire de la qualité, on cherche à
pinailler. Je retiens la proposition.

Par ailleurs, pour des raisons de sécurité, tout script CGI devrait
être développé avec l'option -T active. Dans ce cas, il vous faudra
écrire un bout de code permettant d'"untaint"er les valeurs récupérées
via 'param'. C'est en général dans cette partie qu'on
gère/détecte/filtre les différentes situations : si le paramètre n'est
pas définie mais aussi s'il est défini avec une valeur incohérente,
illogique ou interdite, s'il est défini plusieurs fois ou s'il est mal
encodé, etc. ce qui augmente le nombre de cas à gérer et qui empêche
la concision du test...


Pour être franc, là, je n'ai pas tout compris...
--
Paul

Avatar
Paul Gaborit
À (at) Wed, 26 Oct 2005 20:51:04 +0200,
paul POULAIN écrivait (wrote):
[...]
Pour être franc, là, je n'ai pas tout compris...


Lorsqu'on reçoit des données provenant d'un formulaire Web, il faut
évidemment vérifier que les valeurs sont définies mais aussi qu'elles
correspondent à quelque chose de logique (d'un point de vue
applicatif). Donc un simple test général nest pas suffisant. Le test
complet dépend de la nature de chaque information (on ne vérifie pas
une date ou une adresse e-mail de la même manière).

Par ailleurs, l'option -T (le "taint mode") permet de s'assurer un peu
plus que chaque donnée externe a bien été vérifiée avant d'être
utilisée (pour en savoir plus, voir perlsec).

Les deux combinés font que la traitement d'une donnée de formulaire ne
peut pas être réduit à une simple ligne...

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>