2016-01-29 2 views
1

Mon script accepte actuellement chaîne de date ActiveSupport comme argument de ligne de commande:Alternatives à "eval" pour l'analyse de la date de ActiveSupport

my_script --mindate 1.day 

J'utilise eval pour le stocker dans ma config

MyScript.configuration.min_date = eval(min_date_string) 
intérieur mon script

Je comprends que c'est extrêmement douteux et peu sûr car tout peut être transmis à eval, mais quelles sont mes alternatives?

Répondre

2

Vous voulez des durées de temps? Je suppose que vous pouvez utiliser chronic_duration. Mais comme c'est l'heuristique du langage naturel, il ne devient pas entièrement bien défini exactement quelles sortes de chaînes il reconnaîtra. Mais il fera des choses fantaisistes comme "1 jour et 4 heures".

Ou vous pouvez écrire votre propre analyseur/interpréteur très simple pour l'argument. Juste divisé sur un espace (pour "1 jour" type d'entrée) ou un point (pour "1.jour") type d'entrée. Reconnaître quelques mots dans la deuxième position ("heure", "minute" "jour", "mois", "année"), les traduire en secondes, multiplier le nombre par le mot traduit en secondes. Une douzaine de lignes de rubis probablement.

Ou vous pouvez même profiter de la fonctionnalité ActiveSupport qui prend en charge des choses comme "1.day" pour le rendre encore plus facile.

str = "11 hours" 
    number, unit = str.split(' ') 
    number.to_i.send(unit) 

Cela permettrait à l'utilisateur de la ligne de commande d'envoyer une méthode à un numéro. Je ne suis pas sûr que ça compte. D'ailleurs, je ne suis pas sûr si l'original eval importe vraiment ou pas - mais je suis d'accord avec vous c'est une mauvaise pratique. Pour cette question, probablement aussi send sur l'entrée de l'utilisateur, mais pas tout à fait aussi mauvais.

Ou vous pouvez simplement leur faire envoyer le nombre brut de secondes et les calibrer eux-mêmes.

my_script --mindate 86400 

Vous réalisez 1.day finit juste par être converti en nombre de secondes dans une journée normale, non? Je ne sais pas pourquoi vous appelez un certain nombre de secondes "mindate", mais c'est votre affaire!

modifier Ou encore une autre alternative, leur faire faire:

my_script --mindays 2 --minhours 4 --minminutes 3 

ou quelque chose.

0

Comment votre script est appelé? Est-ce que cela va toujours être appelé par un utilisateur avec un compte sur n'importe quelle machine qui l'exécute? Est-ce que cela va être appelé par un service web, ou que quelqu'un sans accès à la machine puisse l'appeler à distance avec ses propres arguments? Si les utilisateurs ne les appellent que si ces utilisateurs ont déjà accès à la commande ruby ou irb, vous ne pouvez pas les autoriser à faire quoi que ce soit qu'ils ne peuvent pas faire en appelant eval. Si elle est appelée à distance, vous ne devriez probablement pas utiliser eval. Ou, une solution rapide et sale pourrait être de faire correspondre les modèles que vous allez évaluer avec une regex.Quelque chose comme /^[0-9]+(\.[a-z_0-9]+){,2}$/ assurerait que c'est dans les 2 appels de méthode d'un littéral Fixnum avant d'évaluer.

+0

Je suis d'accord avec vous, ce n'est probablement pas un gros problème. Mais probablement mieux vaut prévenir que guérir. Bien sûr, quelqu'un avec l'accès en ligne de commande peut déjà exécuter n'importe quel ruby ​​qu'ils veulent. Mais alors vous écrivez votre utilitaire, et plus tard vous finissez par l'utiliser d'une manière ou d'une autre, vous finissant par être appelé avec un argument passé depuis l'entrée user_remote_, oups vous venez de donner l'utilisateur distant RCE, et vous Je ne m'en rendrai probablement jamais compte, car il passe par quelques étapes, et vous avez oublié que l'argument de la ligne de commande a fini par être évalué. – jrochkind