J'aimerais prendre un moment pour répondre à la prémisse de votre question - que eval() est " maléfique ". Le mot " maléfique Le terme "dangereux", tel qu'il est utilisé par les personnes travaillant dans les langages de programmation, signifie généralement "dangereux", ou plus précisément "capable de causer beaucoup de dégâts avec une commande d'apparence simple". Alors, quand est-il acceptable d'utiliser quelque chose de dangereux ? Quand vous savez quel est le danger et quand vous prenez les précautions appropriées.
Pour en venir au fait, examinons les dangers de l'utilisation de eval(). Il existe probablement de nombreux petits dangers cachés, comme pour tout le reste, mais les deux grands risques - la raison pour laquelle eval() est considéré comme un mal - sont les performances et l'injection de code.
- Performance - eval() exécute l'interpréteur/compilateur. Si votre code est compilé, c'est un gros problème, car vous devez appeler un compilateur potentiellement lourd au milieu de l'exécution. Cependant, JavaScript est encore principalement un langage interprété, ce qui signifie que l'appel à eval() n'est pas un gros problème de performance dans le cas général (mais voir mes remarques spécifiques ci-dessous).
- Injection de code - eval() exécute potentiellement une chaîne de code sous des privilèges élevés. Par exemple, un programme exécuté en tant qu'administrateur/Root ne voudra jamais exécuter eval() une entrée utilisateur, car cette entrée pourrait être "rm -rf /etc/important-file" ou pire. Encore une fois, JavaScript dans un navigateur n'a pas ce problème, parce que le programme est exécuté dans le propre compte de l'utilisateur de toute façon. Le JavaScript côté serveur pourrait avoir ce problème.
Venons-en à votre cas spécifique. D'après ce que j'ai compris, vous générez les chaînes vous-même, donc en supposant que vous faites attention à ne pas permettre à une chaîne comme "rm -rf quelque chose d'important" d'être générée, il n'y a pas de risque d'injection de code (mais n'oubliez pas que c'est le cas de très très dur pour s'en assurer dans le cas général). De plus, si vous vous exécutez dans le navigateur, l'injection de code est un risque assez mineur, je crois.
Pour ce qui est des performances, vous devrez les comparer à la facilité de codage. Je pense que si vous analysez la formule, vous pouvez tout aussi bien calculer le résultat pendant l'analyse plutôt que de lancer un autre analyseur (celui qui se trouve dans eval()). Mais il peut être plus facile de coder en utilisant eval(), et l'impact sur les performances sera probablement imperceptible. Il semble que eval() dans ce cas ne soit pas plus maléfique que toute autre fonction qui pourrait éventuellement vous faire gagner du temps.
7 votes
La plupart des bibliothèques JSON n'utilisent pas, en fait, eval sous le capot, exactement pour se protéger contre les risques de sécurité.
13 votes
@Sean - JQuery et Prototype utilisent tous deux eval (JQuery l'utilise via new Function).
8 votes
@plodder - D'où tenez-vous vos informations ? jQuery utilise la fonction native JSON.parse() depuis la version 1.4 (en 2010) ! Voyez par vous-même : code.jquery.com/jquery-1.4.js
1 votes
@ken,Sean il utilise JSON.parse si elle est disponible ce n'est pas le cas pour IE<=7
0 votes
@tobyodavies - bon point, sauf que dire IE<=7 est trompeur, puisque TOUT navigateur vieux de plus de quelques années n'aura pas d'objet JSON natif. et ce que j'essayais de dire, c'est que les librairies JS n'ont pas préférez
eval()
.... c'est juste une solution de repli pour héritage les navigateurs.0 votes
@ken, également un bon point, cependant IE6 & IE7 sont encore très largement utilisés, je les qualifierais d'anciens, pas sûrs de l'héritage - ils sont loin d'être morts, malheureusement. Définitivement, ils ne le préfèrent pas, mais ils l'utilisent dans certaines situations, donc ils pensent qu'il est assez sûr avec certaines contraintes.
0 votes
Une autre discussion plus centrée sur javascript sur ce sujet se trouve à l'adresse suivante stackoverflow.com/questions/4812288/
4 votes
"Il est évident que l'on doit utiliser eval() pour analyser JSON" -- ce n'est pas vrai, au contraire - on ne devrait pas utiliser eval pour analyser JSON ! Utilisez le json2.js de Douglas Crockfords (créateur de JSON) script de json.org !
17 votes
@Tomas l'ironie est que json2.js utilise eval pour analyser JSON.
1 votes
@tobyodavies, wow, c'est intéressant, en gardant à l'esprit que Douglas critique cela. Au moins, il y a de lourds contrôles de sécurité.
1 votes
@Tomas, +1. En fait, vous ne pouvez pas utiliser
eval
pour analyser correctement toutes les chaînes JSON.JSON.parse(' "\u2028" ')
fonctionne maiseval(' "\u2028" ')
échoue avec une exception parce que U+2028 est une nouvelle ligne JavaScript mais est autorisé dans JSON non encodé.1 votes
Utilisation de
eval
peut révéler le code d'implémentation de votre bibliothèque, car il s'exécute à partir de la fermeture. L'impact sur les performances est également important, car il analyse et compile à chaque fois. AvecFunction
cela peut être évité.Function
exécuté dans la fermeture globale indépendamment de l'endroit où il est invoqué. Si vous prévoyez d'appeler cette fonction plusieurs fois, elle peut devenir "chaude" et le moteur JavaScript l'optimise. Et puisqu'elle renvoie un objet fonction, vous pouvez le stocker dans le cache pour limiter les appels àFunction
constructeur.0 votes
@tobyodavies Vrai, cependant Crockford dit n'utilisez pas json2.js sauf si vous avez besoin du support d'IE 8 .
0 votes
@jkdev Lorsque cette question a été posée, IE8 était le navigateur dominant, IE9 avait à peine un an. Et Crockford n'a ajouté cette mention qu'il y a deux semaines (près de trois ans après mon dernier commentaire).
0 votes
Wow, il y a juste 2 semaines ? Je ne le savais pas.
0 votes
Je comprends le point de vue de Crockford sur les risques d'évaluation d'un code malveillant intégré dans JSON. Comme le dit @TMS, il y a
0 votes
@ToolmakerSteve json2.js : Vous avez raison de dire que, du point de vue de l'utilisateur, la façon dont JSON.parse() est implémenté sous le capot n'a pas d'importance. IE8 ne dispose pas de l'objet JSON intégré, il faut donc utiliser json2.js de Crockford comme une alternative plus sûre à
eval
JSON dans votre code. C'est à peu près tout ce qu'il y a à faire.2 votes
"pour analyser les fonctions saisies par l'utilisateur (pour une fonctionnalité de type feuille de calcul)" me suggère qu'une grande partie de la préoccupation concernant l'évaluation est injustifiée. En supposant que la fonction n'est pas persistée dans la base de données, quel mal une fonction javascript peut-elle avoir au niveau d'un seul utilisateur et d'une seule page ? Pirater ses propres données ? Si la fonction est persistante et non partagée, là encore, le problème est limité à l'utilisateur. Persistante et partagée (ou vue par d'autres), oui, vous avez un vecteur d'injection XSS.
1 votes
eval
est toujours mauvais. Il n'y a pas d'exception, point final. Lorsque vous voulez évaluer un code, utilisezwindow.Function
. Bien sûr, il y a des cas où vous pouvez faire des choses avec eval qui ne peuvent pas être faites autrement, mais ce sont des cas d'utilisation illégitimes qui ne devraient jamais être effectués par tout codeur qui se respecte.1 votes
Mozilla est parfaitement clair : N'utilisez jamais eval !
1 votes
N'oubliez pas qu'eval est incompatible avec tous les outils auxquels vous pouvez penser, ESLint, Prettier, UglifyJS, la plupart des fonctions des éditeurs/IDE... et vos collègues ne l'apprécieront pas s'ils sont professionnels. Trouver un moyen détourné de faire quelque chose peut sembler intelligent pour résoudre un problème immédiat, mais ce n'est pas le cas à long terme.