OVH Cloud OVH Cloud

eval

14 réponses
Avatar
Nicolas
Bonjour,

eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1
}
} ;

fait exactement ce dont j'ai besoin, mais

$formule = '${$Tableau{A}}[$i+1] = ${$Tableau{A}}[$i] + 1' ;
eval {
for (my $i = 0 ; $i < $nb_fois ; $i++) {
$formule
}
} ;

ne fait rien, même pas un message d'erreur. Pourquoi ?

Merci. Nicolas.

--
Powered .~.
by Linux /V\ Enlever
------ // \\ Take off
solutions for /( )\ BULBA
smart penguins ^`~'^

4 réponses

1 2
Avatar
Nicolas

2- si on ne fait pas totalement confiance à la source extérieure de
formules ou si on veut pouvoir limiter les fonctions accessibles à un
sous-ensemble bien déterminé de fonctions Perl ou si la syntaxe
utilisée n'est pas exactement celle de Perl, il faudrait alors passer
par la définition d'une grammaire et d'un parser de cette grammaire
(en utilisant Parse::Yapp ou Parse::RecDescent par exemple). Et dans
ce cas, on peut (on doit même) se passer de 'eval "..."'.

Toutes les approches intermédiaires (entre 1 et 2 qui sont les
extrêmes) sont envisageables. En revanche, en terme de sécurité, la
quasi totalité des approches intermédiaires seront du même niveau que
la solution 1 (c'est à dire non sûre).


C'est bien ce que j'ai envisagé :
Comme tu l'as remarqué la commande latex

RempRec[i={0:1:10}]{A[i+1]=A[i]+1}

ne laisse pas beaucoup de place à l'improvisation,
mon script perl le traduit de la sorte :

sub Recurence { # [$argument]{formule}
my ($argument , $formule) = @_ ;

# on cherche i={a:b:c}
my ($depart, $pas, $nb_fois) = ($1,$2,$3) if
$argument =~ /i={(.+):(.+):(.+)}/ ;

# mise en place de la formule
my $motif ;
my $remplace ;
while ( $formule =~ /(w+)(?=[)/ ) {
$motif = $1 ;
$remplace = '${$Tableau{' . "$motif" . '}}' ;
$formule =~ s/$motif/$remplace/g ;
}
$formule =~ s/i/$i/g ;

my $Eval = ' my $i ; '.
' for ( my $I = 0 ; $I < $nb_fois ; $I++) {'.
' $i = $depart + $I*$pas ;'.
" $formule".'}' ;

eval $Eval ;

return "" ;
}

Je reste ouvert à tout suggestions.

Nicolas.

--
Powered .~.
by Linux /V Enlever
------ // Take off
solutions for /( ) BULBA
smart penguins ^`~'^

Avatar
Nicolas

Il y a le package Safe qu'il pourrait être intéressant d'examiner, de ce
point de vue.


Merci pour l'idée et en effet l'auteur de script perl (pére) qui
prédigère le souce latex avant de l'envoyer à latex l'utilisait, mais
les limitations imposées sont trop importantes : impossible d'avoir le
moindre eval dans les script écrits ensuite (fils), les pragma et les
modules chargés par le script père ne sont pas accessibles dans les
script fils et impossible de les charger ensuite ...

L'auteur à donc mis une option nosafe qui désactivait Safe mais les
script perl étaient quand même exécutés dans un reval ce qui n'enlève ps
les limitations modules-pragma ...

J'ai tout viré et bien évidemment ya plus aucune sécurité.

Mais bon, je crois que peu de gens qui récupèrent les sources d'un
programme, le compilent et l'installent eux-mêmes vérifient qu'il ne
contient pas un cheval de Troie ou bien des fontions destinées à nuire.
Comme c'est dit dans la préface du bouquin perl de chez O'Reilly il faut
un minimum de confiance. Ici c'est pour échanger des sources latex avec
des collègues de maths, et surtout leur éviter d'apprendre perl eux qui
ont déjà fait l'effort d'apprendre latex.

S'il apprennent perl alors la solution la plus élégante est alors de
produire directement du source latex et le compiler ensuite. J'ai un
certains nombre de ces scripts et je compte les interfacer par des
commande latex. Voilà l'idée actuelle.

Merci pour vos conseils, je reste ouvert suggestion.
N'hésitez pas à insister, j'ai parfois la comprennette difficile ;-)

Nicolas.

--
Powered .~.
by Linux /V Enlever
------ // Take off
solutions for /( ) BULBA
smart penguins ^`~'^

Avatar
Paul Gaborit
À (at) Tue, 17 Jan 2006 15:55:54 +0100,
Nicolas écrivait (wrote):
C'est bien ce que j'ai envisagé :
Comme tu l'as remarqué la commande latex

RempRec[i={0:1:10}]{A[i+1]=A[i]+1}

ne laisse pas beaucoup de place à l'improvisation,


Si la syntaxe est bein vérouillée, la passage par un parser devient
intéressant et permet dans la plupart des cas de se passer de la
former 'eval "..."'. Elle reste tout de même intéressant parfois pour
des raisons de performances (mais pour votre application je doute que
ce soit vraiment le point clé).

Une autre possibilité pour éviter quelques problèmes évidents de
sécurité est d'activer l'option '-T' de perl. Cela oblige à parser via
une regexp (ou équivalent) toutes les valeurs venant de l'extérieur du
script. Ce n'est pas la sécurité à 100% mais ça aide pas mal à faire
des trucs propres.

mon script perl le traduit de la sorte :

sub Recurence { # [$argument]{formule}
my ($argument , $formule) = @_ ;

# on cherche i={a:b:c}
my ($depart, $pas, $nb_fois) = ($1,$2,$3) if
$argument =~ /i={(.+):(.+):(.+)}/ ;


Un 'my' conditionnel n'a pas de sens. C'est d'ailleurs très ambigu et
il n'est pas sûr que Perl l'interprêtera toujours comme il le fait
actuellement.

Il vaut mieux écrire :

my ($depart, $pas, $nb_fois);
($depart, $pas, $nb_fois) = ($1,$2,$3)
if $argument =~ m/i={(.+):(.+):(.+)}/;

... et se poser la question "Que se passe-t-il si ça ne matche pas ?"
et donc réécrire sous la forme :

my ($depart, $pas, $nb_fois);
if ($argument !~ m/i={(.+):(.+):(.+)}/) {
die "Erreur de syntaxe...n"; #
}
($depart, $pas, $nb_fois) = ($1,$2,$3);

ou alors :

my ($depart, $pas, $nb_fois) = $argument =~ m/i={(.+):(.+):(.+)}/;
if (not defined $depart or not defined $pas or not defined $nb_fois) {
die "Erreur de syntaxe...n"; #
}

ou... Il y a encore mille façons d'écrire la même chose. ;-)

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

Avatar
Nicolas
Une autre possibilité pour éviter quelques problèmes évidents de
sécurité est d'activer l'option '-T' de perl. Cela oblige à parser via
une regexp (ou équivalent) toutes les valeurs venant de l'extérieur du
script. Ce n'est pas la sécurité à 100% mais ça aide pas mal à faire
des trucs propres.


Je vais voir ce que cela fait.

Un 'my' conditionnel n'a pas de sens. C'est d'ailleurs très ambigu et
il n'est pas sûr que Perl l'interprêtera toujours comme il le fait
actuellement.


En fait ça fait ce que je veux, car comme j'ai un use strict, si àa
match pas les variables ne sont pas déclarées, à la première utilisation
y a Global...
L'idée c'est qu'il n'y ai pas de message d'erreur perl, sauf Global ...
car c'est destiné à des utilisateur qui ne sont pas sensés connaître
perl, cela doit rester transparent. Global ... c'est qu'ils utilisent
une variables non initialisée.

Il vaut mieux écrire :

my ($depart, $pas, $nb_fois);
($depart, $pas, $nb_fois) = ($1,$2,$3)
if $argument =~ m/i={(.+):(.+):(.+)}/;


Je suis d'accord avec toi et je mettrai même :

my ($depart=0, $pas=1, $nb_fois=0);

Comme cela la liste sensée être produite est crée, mais elle n'aura pas
la longueur souhaitée et l'utilisateur vérifiera les paramêtres de la
boucle.

die "Erreur de syntaxe...n"; #


die est rigoureusement interdit ici ;-)

Nicolas.

--
Powered .~.
by Linux /V Enlever
------ // Take off
solutions for /( ) BULBA
smart penguins ^`~'^

1 2