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$
  • 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$ – Leonid Shifrin Jan 4 '16 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 Jan 4 '16 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$ – Leonid Shifrin Jan 4 '16 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$ – Leonid Shifrin Jan 4 '16 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 Jan 4 '16 at 17:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.