59
$\begingroup$

LaTeX on this site supports \newcommand and \renewcommand. This is very nice, but I noticed that the scope of these definitions is the entire rest of the page. That's consistent with how LaTeX behaves, but it could be undesirable on this site where the page contains posts by different people: one person's \newcommand affects everyone who posts below them.

To illustrate the problem, in this question I am including

\renewcommand{\sin}{\cos}

$\renewcommand{\sin}{\cos}$Now anyone who uses \sin in an answer or a comment will get $\cos$ instead.

(I considered exploiting this when asking some simple trig question on main and then watching the confusion, but decided not to be evil.)

It would be good if the scope of \newcommand and friends could be limited to the current question/answer/comment, but I don't know whether this is possible.

$\endgroup$
18
  • 15
    $\begingroup$ Let's try an example in a comment: $\sin \pi = 0$. Indeed, it makes me look like a fool. $\endgroup$ Commented May 4, 2012 at 22:17
  • 2
    $\begingroup$ This is a known issue. $\endgroup$ Commented May 4, 2012 at 22:20
  • 20
    $\begingroup$ This is known, but this can be rather easily remedied: You can edit the malicious post; you can \renewcommand; and you can flag for moderator with a comment explaining what is happening. Perhaps we should institute a norm that whenever someone is intentionally breaking $\LaTeX$ the post will be flagged for moderator attention (even after correcting) and the moderators will warn the user, since breaking math display on a mathematical site is a first-degree level of trolling! $\endgroup$
    – Asaf Karagila Mod
    Commented May 4, 2012 at 22:26
  • 2
    $\begingroup$ I made things worse! :-D $\renewcommand{\cos}{\sum}\renewcommand{\sum}{\stackrel{\circ\cdot\circ}{\Huge \smile}}\renewcommand{\pi}{\text{BAM! You have been trolled!}}$ $\endgroup$
    – Asaf Karagila Mod
    Commented May 4, 2012 at 22:56
  • 8
    $\begingroup$ Maybe this is a dumb question, but why should the site allow \renewcommand? I can understand \DeclareMathOperator and \newcommand which seem much less dangerous because clashes are rather unlikely, but I can't think of a really good use of \renewcommand. $\endgroup$
    – t.b.
    Commented May 4, 2012 at 23:26
  • 4
    $\begingroup$ Someone could want to copy over latex code that they already have with their custom commands. $\endgroup$
    – Phira
    Commented May 5, 2012 at 0:52
  • $\begingroup$ What if a second \newcommand or \renewcommand was in the comments? $$\renewcommand{\sin}{\left.{{\unicode{x263A}}\atop{\unicode{x263A}}}\right)}$$ $\endgroup$ Commented May 5, 2012 at 4:40
  • $\begingroup$ @J.M.: As my previous comment shows, it breaks things just as well. In which case flagging for a moderator attention is needed. $\renewcommand{sin}{\text{Beer is Good!}}$ $\endgroup$
    – Asaf Karagila Mod
    Commented May 5, 2012 at 12:14
  • $\begingroup$ I commented about that here some time ago. Related question: meta.math.stackexchange.com/questions/3667/… $\endgroup$
    – Willie Wong Mod
    Commented May 7, 2012 at 7:39
  • 1
    $\begingroup$ @t.b. I would not prohibit them. I personally prefer \geqslant ($\geqslant$) over geq ($\geq$) and thus write \let\geq\geqslant in the beginning of my posts. (I don't want to write \geqslant every time.) Same with \phi ($\phi$) and \varphi ($\varphi$). $\endgroup$ Commented Apr 10, 2015 at 12:29
  • 2
    $\begingroup$ I found that in order to include such definitions, they have to be put between dollar signs so that MathJax can see them. This leads to a space being included, which is the rendering of this empty equation. Is there a way to suppress this space? $\endgroup$
    – A. Donda
    Commented Apr 17, 2015 at 15:56
  • 4
    $\begingroup$ @A.Donda Put it in the same equation as the first usage (or any other existing MathJax), rather than making the definition stand on its own, i.e. $\DeclareMathOperator{\ran}{ran}\ran f=\emptyset$ to get $\DeclareMathOperator{\ran}{ran}\ran f=\emptyset$. $\endgroup$ Commented May 7, 2015 at 18:45
  • $\begingroup$ How dastardly evil! $\endgroup$ Commented Aug 28, 2016 at 12:51
  • $\begingroup$ Possible duplicate of old \def definitions linger $\endgroup$ Commented Apr 6, 2017 at 6:40
  • 1
    $\begingroup$ @A.Donda, the empty space is not the result of rendering the empty equation (which has empty result), but of any following space. For example, $\def\a{a}$ \a results in a space, but $\def\a{a}$\a doesn't. $\endgroup$
    – LSpice
    Commented Nov 29, 2018 at 15:29

5 Answers 5

29
$\begingroup$

It pains me to break this thread by fixing the issue, but here we are. :)

We are now inserting \begingroup and \endgroup directives into post and comment bodies, so all command definitions should be scoped to individual posts.

For now, I'm only enabling this on Math (and here on meta), but barring any issues this change will go live on all MathJax-enabled sites next week.

$\endgroup$
8
  • 3
    $\begingroup$ It seems that the issue isn't completely fixed. See math.meta.stackexchange.com/q/29702/18398 $\endgroup$
    – JRN
    Commented Jan 28, 2019 at 4:25
  • 8
    $\begingroup$ To add a bit more to detail to @Joel's comment: a newcommand in titles can still cause issues. This is especially a problem when a title containing a newcommand appears in "linked" and "related." This can create rather confusing situations. $\endgroup$
    – quid Mod
    Commented Jan 28, 2019 at 8:11
  • 4
    $\begingroup$ It's still broken if you do $\endgroup \renewcommand{\sin}{\cos} \begingroup$ \endgroup \renewcommand{\sin}{\cos} \begingroup. As you can see, it broke the post below. $\endgroup$
    – qbt937
    Commented Feb 10, 2019 at 20:35
  • 4
    $\begingroup$ @qbt937 Yeah... Although honestly, that isn't something that would come up naturally. The only way this'd happen is from someone trying to mess with the page and I'm okay with leaving that up to being edited out and the user potentially being suspended if they keep at it. $\endgroup$
    – Adam Lear StaffMod
    Commented Feb 11, 2019 at 17:46
  • 1
    $\begingroup$ Thanks for making the change. How are you faring with this, is anything rolled out over the other sites already? Or are there still issues to be fixed / high prio tasks taking precedence? Cheers, Maarten, mod at cryptography. Or should we create a feature request to obtain it? $\endgroup$ Commented Mar 5, 2019 at 13:34
  • 5
    $\begingroup$ @MaartenBodewes It's live on every SE site that has Mathjax enabled. You don't need to do anything special. $\endgroup$
    – Adam Lear StaffMod
    Commented Mar 5, 2019 at 16:31
  • 2
    $\begingroup$ Of course, now some of comments and answers are not rendered correctly - if the OP used macro defined in the question. (And, of course, at that time they were rendered fine.) But probably there is not too many of them and some of them might eventually get edited. More on this in chat and in A recent post by quid is somewhat related. And there was a short discussion on MathOveverflow Meta. $\endgroup$ Commented Apr 12, 2019 at 10:39
  • 1
    $\begingroup$ @AdamLear I have posted a follow-up question concerning macros in titles - asking both whether titles should be inside begingroup...endgroup too and to which extent defining macros in the titles should be discouraged. $\endgroup$ Commented Jun 18, 2019 at 7:30
24
$\begingroup$

As Mariano points out, this has been reported before. Because of that conversation, MathJax v2.0 includes an extension (the begingroup extension) that would allow you to isolate the effects of \def, \newcommand, etc. to a single question, answer, or comment, but it would require changes to the SE code to force that to be used.

The changes would be to include begingroup.js in the TeX extensions array for the site's configuration, and outputing a $\begingroup$ at the beginning of each questions/answer/comment and an $\endgroup$ at the end. (These might want to be enclosed in a hidden <div> or some other tag so that they don't introduce any unwanted space.) The preview code would also have to be modified to include these, but that would need to be a bit more sophisticated, since the typesetting can be canceled in the middle (by new characters being typed) so the final \endgroup would need to be handled separately in that case. I would be happy to work that out if the powers-that-be wanted to coordinate efforts on that.

Edit: Asaf asks whether you can do anything like this "by hand". I had considered telling you about the \require{} command that will load extensions that haven't been included in the configuration, but I didn't. That's because the current preview code will not work well with the begingroup extension. If you include a $\begingroup$ in your post, but haven't yet typed the $\endgroup$, then each character you type will cause the post to be reprocessed, and each reprocessing will cause a new \begingroup to be performed without a corresponding \endgroup. This will use up memory that will not be freed (until you go to another page), and can slow MathJax down.

Similarly, if you have a long post, then even if you do have matching \begingroup and \endgroup tags, if you type fast, each letter will cancel MathJax in the middle of what it is doing, and so MathJax may be canceled after processing the \begingroup but before the \endgroup. Again, you can use up memory.

This is what I meant when I said that the preview code would need to be modified to take that into account.

While it is technically possible to use the begingroup extension by hand, you would have to be careful about how you do it. On the plus side, it only affects you when you are editing (or someone else who is editing your work), so perhaps you would be willing to put up with the difficulties.

In any case, your example doesn't really show how it would work, since \begingroup and \endgroup don't protect you from definitions from outside your answer; they protect others from definitions in your answer. So to see it really work, you would need to use something like

$$
  \require{begingroup}
  \begingroup
\renewcommand{\tan}{\operatorname{grey}}
\tan\theta
  \endgroup
  \ne
  \tan\phi
$$

to get

$$ \require{begingroup} \begingroup \renewcommand{\tan}{\operatorname{grey}} \tan\theta \endgroup \ne \tan\phi $$

This works, but if you don't get the balancing of begin and end groups properly during the editing process, you can be left with a lot of open begin groups, that contain local definitions that don't go away (until you reload the page).

$\endgroup$
24
  • 1
    $\begingroup$ Is this workaround applicable "by hand"? (Testing: $\begingroup\sin\neq\cos\endgroup$) $\endgroup$
    – Asaf Karagila Mod
    Commented May 5, 2012 at 20:53
  • $\begingroup$ @AsafKaragila I added material to my original answer about that. $\endgroup$ Commented May 6, 2012 at 10:31
  • $\begingroup$ Yes, I saw. Thank you. Do note that the main problem which Nate pointed is that vandals can post a malicious code and "ruin" the answer. $\endgroup$
    – Asaf Karagila Mod
    Commented May 6, 2012 at 10:40
  • $\begingroup$ Yes, I understand that. That is why I said it would take changes to the SE code to do this properly. I thought you were asking about using \begingroup and \endroup yourself (to isolate your local macros so they don't interfere with others). Perhaps I misunderstood. I do not see a way to prevent others from making definitions without changes to SE code. $\endgroup$ Commented May 6, 2012 at 11:46
  • $\begingroup$ I was hoping that there would be a way to locally reset inside an answer. $\endgroup$
    – Asaf Karagila Mod
    Commented May 6, 2012 at 11:50
  • 2
    $\begingroup$ I suppose if the questioner added $\require{begingroup}\begingroup$ at the bottom of the question, you could use $\endgroup\begingroup$ at the top and bottom of your answer or isolate your response from the effects of others (and localize your changes to your answer as well). But this takes cooperation of the questioner, and it also has all the preview problems that I mentioned. $\endgroup$ Commented May 6, 2012 at 11:50
  • $\begingroup$ That is effectively what I am suggesting that the SE code does between each question/answer/comment, but you could do it by hand for your answer provided there was an initial \begingroup in the question. $\endgroup$ Commented May 6, 2012 at 11:54
  • $\begingroup$ Of course that would still only prevent accidental macro leaking, not malicious leaking. For one, the begingroup extension also provides \gdef, which works around \begingroup/endgroup. Moreover, even without \gdef, a malicious poster could simply use\endgroup\renewcommand{\sin}{\cos}\begingroup to make his definition intentionally leaking. So if the goal is to prevent malicious behaviour, it has to use a mechanism which isn't accessible to users. $\endgroup$
    – celtschk
    Commented Jul 13, 2012 at 7:10
  • $\begingroup$ Your point is well taken, but I think it could be handled as follows: make a new macro \reset that does the action of \endgroup\begingroup (easily done), and remove the \begingroup, \endgroup, \gdef, and \global macros. Use $\reset$ between questions/answers/posts, and rather than call MathJax's typeset by itself, first queue the \begingroup function directly, then the typeset then the \endgroup function. While the user could still call \reset in her message, it would not provide a means of entering global definitions. $\endgroup$ Commented Jul 13, 2012 at 10:38
  • $\begingroup$ @DavideCervone: If you make \reset completely reset the MathJax engine (i.e. remove even macros defined globally), there's no need to remove the macros from the begingroup extension. But you're right, \reset being available to users would not be harmful. $\endgroup$
    – celtschk
    Commented Jul 14, 2012 at 10:25
  • $\begingroup$ @Davide: I added a fix for this issue into SOUP, but it's kind of crude: I'm basically just injecting the equivalent of $\endgroup$ $\begingroup$ at the beginning of each post and comment. It's working, but if you'd have any suggestions on how to do it more cleanly / elegantly, please do tell. The current code I have is here (look for mathJaxSetup). $\endgroup$ Commented Jan 15, 2014 at 21:15
  • $\begingroup$ @IlmariKaronen, what you have looks good except for two things: (1) you don't need to have two separate expressions, you could just do $\endroup\begingroup$, and (2), it is possible for a user to redefine \endgroup or \begingroup within their post. Preventing that would require overriding part of MathJax's code for defining macros (but it could be done). Also, make sure you first post only starts with $\begingroup$ with no leading \endgroup, and your last one should only have $\endgroup$. $\endgroup$ Commented Jan 16, 2014 at 16:05
  • $\begingroup$ @DavideCervone: The reason I'm using two separate expressions is precisely so that if \endgroup fails (because the stack is already empty), the following \begingroup will still run. While I could omit the first \endgroup and the last \begingroup on the page as you suggest, having new posts or other content loaded via AJAX could still cause subsequent typeset passes to start with an unbalanced \endgroup, so I have to tolerate that possibility. What I'd really like to do is implement your / celtschk's \reset idea above, but I don't know enough about MathJax internals to see how. $\endgroup$ Commented Jan 16, 2014 at 19:50
  • 1
    $\begingroup$ @DavideCervone: OK, I did figure out how to do it by monkey-patching parts of the begingroup extension. It's a bit complicated, and likely to break if the extension ever gets rewritten, but otherwise it works very nicely. $\endgroup$ Commented Jan 16, 2014 at 22:50
  • $\begingroup$ @IlmariKaronen, actually, I quite like it over all. Would you might if I incorporate something similar into the begingroup extension directly? You use an approach I hadn't thought of, and I think it works nicely (as you point out). BTW, there are a couple of other things that could be added to SOUP that I might suggest, but this is not the right pace for that. Where is best to discuss such things? $\endgroup$ Commented Jan 17, 2014 at 14:38
10
$\begingroup$

This answer will serve as a demonstration:

$$\sin \pi = 0$$

What I typed was true (edit or view source), but what you see is false.

$\endgroup$
1
  • 3
    $\begingroup$ When $\sin$ is $\sin$ and $\cos$ is $\sin$! Pythagoras rolls over in his unmarked grave. $\endgroup$
    – Asaf Karagila Mod
    Commented May 4, 2012 at 22:38
10
$\begingroup$

$\require{begingroup} \begingroup$As discussed in the comments to Davide Cervone's answer, I have added a client-side fix to this bug to version 1.2. of the Stack Overflow Unofficial Patch.

The fix works by injecting a special hidden TeX command (currently named \resetstack) at the beggining of each post, comment, snippet (as shown e.g. on the front page) or question/answer link (as in the sidebar), which resets the TeX InputJax macro definitions to their default values.

The implementation is currently a bit complicated, but hopefully it can be simplified later, if some of the needed code is incorporated directly into MathJax as Davide suggests in the comments.

Some important notes about the fix:

Since SOUP is a client-side user script, installing it will fix the bug for you, but not for others. In particular, any definitions made in your posts will still leak to other posts when viewed by users who don't have SOUP installed (which, alas, means most of them).

I therefore strongly recommend that, if you use \def, \(re)newcommand or other such features in your posts, you should always prefix them with:

$\require{begingroup} \begingroup$

and end them with:

$\endgroup$

to keep your definitions from leaking into other posts. (Note that using SOUP should eliminate any memory leak issues due to unclosed \begingroup tags while composing a post, since SOUP will reset the definition stack whenever the preview pane is re-typeset.)

You should also avoid redefining symbols in question titles, or anywhere near the top of your posts where the definitions would be likely to show up on the front page or in search results. (Alas, there's currently no 100% reliable way to prevent that from happening, except by not redefining TeX commands at all.)

Because of these issues, \def and friends are still best used sparingly, and only for things that would be unlikely to conflict with notation in other posts. For example, \newcommand{\foo}{\operatorname{foo}} is probably fine, but \newcommand{\sin}{\cos} is not.

Also note that, even with SOUP, definitions imported from extensions via \require will still leak into other posts. This is pretty much impossible to avoid without breaking some extensions badly, and should basically be considered as being by design.$\endgroup$


Edit: Turns out that my original implementation of this fix suffered from a race condition that made it work on Firefox only occasionally. This should be fixed in v1.2.1 that I just released; anyone using it is strongly advised to upgrade.

(Also, the upcoming v1.4 release of SOUP will have more MathJax scoping fixes, including one for \labels, again based on a suggestion by Davide Cervone. Those still need some more testing before release, though.)

$\endgroup$
8
  • $\begingroup$ Is it possible that SOUP could implement some sort of autosave feature to prevent loss of work due to frequent Chrome + MathJax crashes? The problem is so severe that I don't even dare to use MathJax with Chrome any more (except for trivial answers), having already lost countless hours of work due to such crashes. $\endgroup$ Commented Jan 18, 2014 at 15:56
  • $\begingroup$ @Bill: The SE editor is already supposed to autosave posts, although only every 45 seconds. Of course, the real problem here is MathJax crashing Chrome, which presumably counts as a bug in both MathJax and Chrome. FWIW, I suspect things may have improved somewhat -- I use both Firefox and Chrome, and do recall experiencing poor rendering and slowdowns during editing (if not outright crashes) on the latter in the past, but not so much recently (except on the Android version of Chrome, which does get bogged down by lots of math). $\endgroup$ Commented Jan 18, 2014 at 16:04
  • $\begingroup$ Alas, the SE "autosave" feature is a kludge that works only rarely to recover from Chrome crashes. Any heavy use of MathJax + Chrome causes frequent Chrome crashses, making MathJax essentially unusable on Chrome. It's been this way for many years now. If it cannot be fixed, it would be really, really great to have some workaround, if that is not too much trouble to implement. This is by far the worst software problem I've encountered in a few decades of heavy software use. It's a shame that it has gone on this long. You can see many complaints about it in old meta posts. $\endgroup$ Commented Jan 18, 2014 at 16:47
  • $\begingroup$ I agree. I can't really fix it without knowing why it happens, though, and I don't think anyone's really figured that out yet. (If someone has, please do tell me.) $\endgroup$ Commented Jan 18, 2014 at 16:49
  • $\begingroup$ I highly doubt it will ever happen. David claims it is a bug in Chrome tckled by MathJax. So the only hope is a workaround. Surely it must be very easy to implement a halfway decent autosave feature in SOUP, right? This would be the best thing since sliced bread. It would save many Chrome users countless hours of lost work. $\endgroup$ Commented Jan 18, 2014 at 17:05
  • $\begingroup$ It might be possible using LocalStorage, although if Chrome crashes badly enough, that might not be perfectly safe either. I've never actually used LocalStorage before, but I could take a look into it. I'd also have to find some way to keep it from fighting with the SE builtin autosave feature, though. $\endgroup$ Commented Jan 18, 2014 at 17:11
  • $\begingroup$ Thanks! Even something more primitive such as saving to the clipboard would be helpful. The goal is to guarantee that one will not lose much work even if the browser crashes (which is very far from true for the SE draft saving feature) $\endgroup$ Commented Jan 18, 2014 at 17:36
  • $\begingroup$ Javascript doesn't have access to the clipboard (for security reasons), so that is not likely to be a solution. There are some Flash-based kludges, but in general, browsers prevent javascript frmo modifying the clipboard. $\endgroup$ Commented Jan 18, 2014 at 22:42
0
$\begingroup$

Fun fact:

in addition to

\newcommand{\sin}{\cos}

you can also include

\newcommand{\cos}{\sin}

and flat-out break all the code that uses those commands. Or, if you felt inclined to be evil, you could e.g. do a cyclic redefinition of the entire Greek alphabet, or something. Not that you should, of course.

$\endgroup$
3
  • 3
    $\begingroup$ How does this contribute to the discussion? $\endgroup$
    – Asaf Karagila Mod
    Commented Mar 16, 2017 at 7:14
  • 6
    $\begingroup$ It illustrates how bad this bug is $\endgroup$
    – Nick Alger
    Commented Jun 21, 2017 at 1:55
  • 1
    $\begingroup$ In case it is not obvious, this pair of definitions will not swap the roles of \sin and \cos. Rather, it will make both macros unusable, as they are now defined by mutual recursion that never comes to an end, leading to a “MathJax maximum macro substitution count exceeded” error. $\endgroup$ Commented Feb 5, 2022 at 10:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .