21
$\begingroup$

Compressed strings are often used to exchange Mathematica expressions on the Internet. It is, however, not easy to see what such expression will do after decompression. Resulting code can perform unwanted evaluations.

Here is a (somewhat stupid) example:

Warning: This will open a Youtube music video when decompressed!

str = "1:eJx9jt0KgkAQhbUfiC6CegOvA70Pogu1CARBX6BNZ1Fad8Wd9e/p200ouvHmY87MnMNxniKhtmVZcqMRtoQpgkAXZnPQ8EVVC8XzsK8bkLIUnFrmtte4c4SGE/ZIyuyVCMYm20rj1pT5FGtUVEr8V+laD8bi/DyJYiB3egiAEsUwZFABR7qc6fIxbzVSwAAYGSCf62d/3weJUMU18PSoZYFYy5PndV3nDkKheoKbicrrCGbFpT0H0dg349UfYjkTn5r4/g2cBFpg";

To see the uncompressed content without evaluation, I have tried to use Defer (as suggested in this answer):

Uncompress[str, Defer]

but it does not prevent the video from being played.

How can I uncompress strings from internet safely, i.e. without any evaluation taking place?

$\endgroup$
  • 1
    $\begingroup$ ToString@Uncompress[str, HoldComplete] works. But I do not understand why the evaluation leaks otherwise. It must leak in the display code (MakeBoxes, etc.) $\endgroup$ – Szabolcs Apr 21 '17 at 17:34
  • $\begingroup$ @Kuba Or ToString[Uncompress[str, HoldComplete], InputForm] $\endgroup$ – Szabolcs Apr 21 '17 at 17:42
  • 6
    $\begingroup$ A simpler version is evaluating: HoldComplete[Grid[{{}}, DefaultElement -> (Print[1]; "x")]] $\endgroup$ – Carl Woll Apr 21 '17 at 19:48
  • 1
    $\begingroup$ Similar: (32296), (88267), (16664) $\endgroup$ – WReach Apr 21 '17 at 21:43
  • 1
    $\begingroup$ I just knew it was going to be that video. xD $\endgroup$ – Mr.Wizard Apr 23 '17 at 13:52
16
$\begingroup$

This is definitely a bug. Here's a slightly simpler workaround than those suggested in the comments:

Uncompress[str, HoldComplete] // InputForm

Generally speaking, InputForm and OutputForm are safer than StandardForm. This is for a couple of reasons. Much more of those textual formats happens inside the raw kernel, where evaluation leaks are easier to control. (I know of a couple, but really only because I can read the source code.) The second reason is that there is a class of evaluation which is allowed to happen during formatting, namely Dynamic evaluation--this allows the FE to ask the kernel to evaluate pieces of the expression in order to display them or respond to user actions. Since the frontend will only do this for box-type (e.g, StandardForm) cells, using InputForm or OutputForm will prevent these evaluations.

Edit and expansion in response to @Kuba's comment:

We do try hard to avoid evaluation leaks during formatting, but it can be quite challenging while also make things look "right" in the way most people want them to. And in, fact, this case (as well as Kuba's) shows one of the design issues that hasn't been quite solved.

DefaultElement is an option to GridBox. Options to boxes generally want expressions, not other boxes, as values. So we don't run MakeBoxes on the input. But if the particular box is not HoldAll, the expression isn't protected from further evaluation once MakeBoxes is done. On the other hand, if the value isn't valid (whatever that means) there basically two possibilities: either disable formatting completely, or format with the value protected somehow (say replacing the Rule by RuleDelayed). But that will result in pink boxing in the FE. You'll notice that completely invalid inputs to typeset generators (say, Grid[{a}]) don't format at all. In other cases, you get pinking (e.g., Hold[Graphics[{Red, Disk[]}]]) (because GraphicsBox is HoldAll). Getting it completely right in all cases? Hard.

|improve this answer|||||
$\endgroup$
  • 4
    $\begingroup$ I was going to post an answer defending this behavior but if you say it is a bug then there is a serious problem out there: HoldComplete[#[True, Appearance -> (Echo@"Frameless")]] & /@ {Framed, Checkbox, Button} $\endgroup$ – Kuba Apr 21 '17 at 21:59
  • 4
    $\begingroup$ @Kuba I am reluctant to call this a bug in Mathematica... but a user program is definitely in error if it uncritically evaluates expressions from untrusted sources. I do agree that it is far too easy to make this mistake using Uncompress (or ToExpression, Import, RunThrough, LinkRead, etc.). It wouldn't hurt if features such as these by default returned expressions that were completely kernel/typesetting inert, requiring additional code to evaluate (to protect us from things less benign than HoldComplete[Dynamic[Echo["rm -rf /"]]]). $\endgroup$ – WReach Apr 22 '17 at 0:35
  • $\begingroup$ @WReach yes, I had it mind something along those lines. And Itai, this problem is not going to go away soon so it would be good to create a chapter in security related tutorial and link this chapter to related functions (e.g. those ementioned above). I think formatting and typesetting steps in MMA are hard to grasp even for more experienced users but security issues have to be clear. ps. Link on top in details and options, not in PossibleIssues, $\endgroup$ – Kuba Apr 24 '17 at 9:51

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.