% language=us runpath=texruns:manuals/lowlevel

% It took some time to get the right balance of using the overload related features
% but at some point it started feeling right. Of course it will never be as
% perfectly timed and integrated as Gavin Harrison performance on "Threatening War"
% (youtube movie) but that doesn't mean I should not aim for perfection. But as
% with drumming, it takes practising and that is what I did on a subset of sources
% when writing the engine code.
%
% It tooks a few weeks but November 21 2020 the last of the core files was turned
% \LMTX, not that the work was done (checking to be done (thanks Wolfgang!), imp
% files to be checked, many \LUA\ files to be updated) but it's a start. This time
% the musical timestamp is listening to Nikola Cvetkovic (piano) and history
% podcasts.

\usemodule[system-tokens]

\environment lowlevel-style

\startdocument
  [title=security,
   color=middleorange]

\startsectionlevel[title=Preamble]

Here I will discuss a moderate security subsystem of \LUAMETATEX\ and therefore
\CONTEXT\ \LMTX. This is not about security in the sense of the typesetting
machinery doing harm to your environment, but more about making sure that a user
doesn't change the behavior of the macro package in ways that introduce
interference and thereby unwanted side effect. It's all about protecting macros.

This is all very experimental and we need to adapt the \CONTEXT\ source code to
this. Actually that will happen a few times because experiments trigger that. It
might take a few years before the security model is finalized and all files are
updated accordingly. There are lots of files and macros involved. In the process
the underlying features in the engine might evolve.

\stopsectionlevel

\startsectionlevel[title=Flags]

Before we go into the security levels we see what flags can be set. The \TEX\
language has a couple of so called prefixes that can be used when setting values
and defining macros. Any engine that has traditional \TEX\ with \ETEX\ extensions
can do this:

\starttyping[option=TEX]
                 \def\foo{foo}
\global          \def\foo{foo}
\global\protected\def\foo{foo}
\stoptyping

And \LUAMETATEX\ adds another one:

\starttyping[option=TEX]
       \tolerant          \def\foo{foo}
\global\tolerant          \def\foo{foo}
\global\tolerant\protected\def\foo{foo}
\stoptyping

What these prefixes do is discussed elsewhere. For now is is enough to know that
the two optional prefixes \type {\protected} and \type {\tolerant} make for four
distinctive cases of macro calls.

But there are more prefixes:

\starttabulate
\HL
\NC \type {frozen}     \NC a macro that has to be redefined in a managed way \NC \NR
\NC \type {permanent}  \NC a macro that had better not be redefined \NC \NR
\NC \type {primitive}  \NC a primitive that normally will not be adapted \NC \NR
\NC \type {immutable}  \NC a macro or quantity that cannot be changed, it is a constant \NC \NR
\NC \type {mutable}    \NC a macro that can be changed no matter how well protected it is \NC \NR
\HL
\NC \type {instance}   \NC a macro marked as (for instance) be generated by an interface \NC \NR
\HL
\NC \type {noaligned}  \NC the macro becomes acceptable as \type {\noalign} alias \NC \NR
\HL
\NC \type {overloaded} \NC when permitted the flags will be adapted \NC \NR
\NC \type {enforced}   \NC all is permitted (but only in zero mode or ini mode) \NC \NR
\NC \type {aliased}    \NC the macro gets the same flags as the original \NC \NR
\HL
\stoptabulate

These prefixed set flags to the command at hand which can be a macro but
basically any control sequence.

To what extent the engine will complain when a property is changed in a way that
violates the above depends on the parameter \type {\overloadmode}. When this
parameter is set to zero no checking takes place. More interesting are values
larger than zero. If that is the case, when a control sequence is flagged as
mutable, it is always permitted to change. When it is set to immutable one can
never change it. The other flags determine the kind of checking done. Currently
the following overload values are used:

\starttabulate[|l|l|c|c|c|c|c|]
    \NC   \NC         \BC immutable \BC permanent \BC primitive \BC frozen \BC instance \NC \NR
    \NC 1 \NC warning \NC \star     \NC \star     \NC \star     \NC        \NC          \NC \NR
    \NC 2 \NC error   \NC \star     \NC \star     \NC \star     \NC        \NC          \NC \NR
    \NC 3 \NC warning \NC \star     \NC \star     \NC \star     \NC \star  \NC          \NC \NR
    \NC 4 \NC error   \NC \star     \NC \star     \NC \star     \NC \star  \NC          \NC \NR
    \NC 5 \NC warning \NC \star     \NC \star     \NC \star     \NC \star  \NC \star    \NC \NR
    \NC 6 \NC error   \NC \star     \NC \star     \NC \star     \NC \star  \NC \star    \NC \NR
\stoptabulate

The even values (except zero) will abort the run. In \CONTEXT\ we plug in a
callback that deals with the messages. A value of 255 will freeze this parameter.
At level five and above the \type {instance} flag is also checked but no drastic
action takes place. We use this to signal to the user that a specific instance is
redefined (of course the definition macros can check for that too).

So, how does it work. The following is okay:

\starttyping[option=TEX]
\def\MacroA{A}
\def\MacroB{B}
\let\MyMacro\MacroA
\let\MyMacro\MacroB
\stoptyping

The first two macros are ordinary ones, and the last two lines just create an alias. Such
an alias shares the definition, but when for instance \type {\MacroA} is redefined, its
new meaning will not be reflected in the alias.

\starttyping[option=TEX]
\permanent\protected\def\MacroA{A}
\permanent\protected\def\MacroB{B}
\let\MyMacro\MacroA
\let\MyMacro\MacroB
\stoptyping

This also works, because the \type {\let} will create an alias with the protected
property but it will not take the \type {permanent} propery along. For that we need
to say:

\starttyping[option=TEX]
\permanent\protected\def\MacroA{A}
\permanent\protected\def\MacroB{B}
\permanent\let\MyMacro\MacroA
\permanent\let\MyMacro\MacroB
\stoptyping

or, when we want to copy all properties:

\starttyping[option=TEX]
\permanent\protected\def\MacroA{A}
\permanent\protected\def\MacroB{B}
\aliased\let\MyMacro\MacroA
\aliased\let\MyMacro\MacroB
\stoptyping

However, in \CONTEXT\ we have commands that we like to protect against
overloading but at the same time have a different meaning depending on the use
case. An example is the \type {\NC} (next column) command that has a different
implementation in each of the table mechanisms.

\starttyping[option=TEX]
\permanent\protected\def\NC_in_table   {...}
\permanent\protected\def\NC_in_tabulate{...}
\aliased\let\NC\NC_in_table
\aliased\let\NC\NC_in_tabulate
\stoptyping

Here the second aliasing of \type {\NC} fails (assuming of course that we enabled
overload checking). One can argue that grouping can be used but often no grouping
takes place when we redefine on the fly. Because \type {frozen} is less restrictive
than \type {primitive} or \type {permanent}, and of course \type {immutable}, the
next variant works:

\starttyping[option=TEX]
\frozen\protected\def\NC_in_table   {...}
\frozen\protected\def\NC_in_tabulate{...}
\overloaded\let\NC\NC_in_table
\overloaded\let\NC\NC_in_tabulate
\stoptyping

However, in practice, as we want to keep the overload checking, we have to do:

\starttyping[option=TEX]
\frozen\protected\def\NC_in_table   {...}
\frozen\protected\def\NC_in_tabulate{...}
\overloaded\frozen\let\NC\NC_in_table
\overloaded\frozen\let\NC\NC_in_tabulate
\stoptyping

or use \type {\aliased}, but there might be conflicting permissions. This is not
that nice, so there is a kind of dirty trick possible. Consider this:

\starttyping[option=TEX]
\frozen\protected\def\NC_in_table   {...}
\frozen\protected\def\NC_in_tabulate{...}
\def\setNCintable   {\enforced\let\frozen\let\NC\NC_in_table}
\def\setNCintabulate{\enforced\let\frozen\let\NC\NC_in_tabulate}
\stoptyping

When we're in so called \type {initex} mode or when the overload mode is zero,
the \type {\enforced} prefix is internalized in a way that signals that the
follow up is not limited by the overload mode and permissions. This definition
time binding mechanism makes it possible to use \type {permanent} macros that
users cannot redefine, but existing macros can, unless of course they tweak the
mode parameter.

Now keep in mind that users can always cheat but that is intentional. If you
really want to avoid that you can set the overload mode to 255 after which it
cannot be set any more. However, it can be useful to set the mode to zero (or
some warning level) when foreign macro packages are used.

\stopsectionlevel

\startsectionlevel[title=Complications]

One side effect of all this is that all those prefixes can lead to more code. On
the other hand we save some due to the extended macro argument handling features.
When you take the size of the format file as reference, in the end we get a
somewhat smaller file. Every token that you add of remove gives a 8~bytes
difference. The extra overhead that got added to the engine is compensated by the
fact that some macro implementations can be more efficient. In the end, in spite
of these new features and the more extensive testing of flags performance is
about the same. \footnote {And if you wonder about memory, by compacting the used
(often scattered) token memory before dumping I manages to save some 512K on the
format file, so often the loss and gain are somewhere else.}

\stopsectionlevel

\startsectionlevel[title=Introspection]

In case you want to get some details about the properties of a macro, you can
check its meaning. The full variant shows all of them.

\startbuffer
% a macro with two optional arguments with optional spacing in between:

\permanent\tolerant\protected\def\MyFoo[#1]#*[#2]{(#1)(#2)}

\meaningless\MyFoo\par
\meaning    \MyFoo\par
\meaningfull\MyFoo\par
\stopbuffer

\typebuffer[option=TEX]

\startpacked \getbuffer \stoppacked

\stopsectionlevel

% In \CONTEXT:
% c! v! s! ??
% newif newcount ... newconditional etc
% userinterface (permanent)
% primitives
% noaligned
% frozen is for users

\stopdocument
