3
$\begingroup$

Consider the following:

example.txt

{TextStyle -> {FontFamily -> "Times"}, Axes -> False, AspectRatio -> Automatic}  
{TextStyle -> {FontFamily -> "Arial", FontSize -> 12}, Axes -> True, AspectRatio -> 1}  
{Frame -> True, Background -> RGBColor[1, 0, 0]}  
{Background -> Red, Axes -> False, AspectRatio -> Automatic}  
  • you have a large text file (example.txt) with several inputs from non-secure users
  • entries that does not correspond to options should be discarded

At first glance you might solve that with OptionQ + ToExpression:

OptionQ[ ToExpression[ line1 ] ]

If line1 is an option then the output is True, otherwise the output is False. However, there is a drawback in this approach. The built-in function ToExpression actualy evaluates the user input, which cause a serious security flaw. Malicious users might run whatever they like in your machine, for example:

{DeleteFile[FileNames[]]}

In this case, ToExpression will evaluate this line and delete all files in your folder, and later OptionQ will tell you that this line is not an option and should be ignored.

Issue
Is there a simple way to check if a text entry is an option without evaluating it?

$\endgroup$
18
  • 2
    $\begingroup$ You can use ToExpression with 3 arguments, for example like ToExpression[codestring, StandardForm, HoldComplete], in which case the code will be parsed but not executed, and will be returned to you wrapped in HoldComplete. You can then analyze the code without evaluating it. $\endgroup$ Commented Jan 4, 2016 at 16:34
  • $\begingroup$ @LeonidShifrin I've just tried the following: msg = "{Method->Automatic}"; OptionQ[ ToExpression[ msg, StandardForm, HoldComplete ] ]; However, the result is False. If you remove the HoldComplete, then the result correctly states True. The same is true with Unevaluated. $\endgroup$
    – Mark Messa
    Commented Jan 4, 2016 at 16:55
  • $\begingroup$ Well, of course OptionQ gives False on an expression with the HoldComplete head. What you may need is slightly more complex, I just suggested the main idea of the solution. The actual code you may need can be something like Select[ StringSplit[text, "\n"], ToExpression[#, StandardForm, Function[expr, OptionQ[Unevaluated[expr]], HoldAllComplete]] &]. $\endgroup$ Commented Jan 4, 2016 at 17:03
  • $\begingroup$ Or, if you want the kept options in already parsed form (which you probably do), you can use e.g. this code: Cases[Map[ToExpression[#, StandardForm, HoldComplete] &, StringSplit[text, "\n"]], HoldComplete[opt_ /; OptionQ[Unevaluated[opt]]] :> opt]. $\endgroup$ Commented Jan 4, 2016 at 17:06
  • $\begingroup$ @LeonidShifrin Great, I've tried the first one and it seems to be working. However, I'm gonna need some time to understand what you have done. Thanks. $\endgroup$
    – Mark Messa
    Commented Jan 4, 2016 at 17:13

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.