n-t-roff / heirloom-doctools

The Heirloom Documentation Tools: troff, nroff, and related utilities
http://n-t-roff.github.io/heirloom/doctools.html
Other
127 stars 23 forks source link

troff: line numbering request .nm 1 causes division by zero after .evc #75

Closed reffort closed 5 years ago

reffort commented 5 years ago

To reproduce, make testfile.tr:

.do xflag 3\" needed for .evc
This is a test of .nm 1...
.br
.ev 1
.evc 0
.nf
.ft CW
.nm 1
Lorem Ipsum
jumped over the
big sphinx of quartz.
.br
.ev
and .nm +0 2 ...
.br
.ev 1
.nm +0 2
There was an old man of St. Bees,
Who was stung in the arm by a wasp,
  When asked, "Does it hurt?"
  He replied, "No, it doesn't,
I'm so glad it wasn't a hornet."
.br
.ev
.nf
Finis.
.nm +0
However, the line numbering counter itself
is global, and is \fInot\fP contained in the environment
along with its settings.

Running

troff testfile.tr | dpost > testfile.ps

results in a "Floating point exception". The error does not occur if .nm 1 is changed to .nm 1 1.

Cause: incorrect initialization in n5.c:evc() sets the value of ndf to zero instead of 1. The user cannot set ndf to zero; it is required to be at least 1 in n5.c:casenm().

By default, there should also be a space between the line numbers and the text. This variable, nds, is also initialized to zero in n5.c:evc() (like ndf, it is set to 1 in ni.c during program initialization).

In effect, .evc changes the defaults from .nm 0 1 1 0 to .nm 0 0 0 0.

Patch:

diff --git a/troff/n5.c b/troff/n5.c
index 2668dd9..df7cf01 100644
@@ -1383,8 +1383,8 @@ evc(struct env *dp, struct env *sp)
    if (dp->_brpnl < INT_MAX)
        dp->_brpnl = 0;
    dp->_nn = 0;
-   dp->_ndf = 0;
-   dp->_nms = 0;
+   dp->_ndf = 1;
+   dp->_nms = 1;
    dp->_ni = 0;
    dp->_ul = 0;
    dp->_cu = 0;

The point of division by zero is in n7.c:donum(). ndf could be tested for zero, with something like:

diff --git a/troff/n7.c b/troff/n7.c
index 90abaec..c9a3562 100644
@@ -292,7 +292,7 @@ donum(void)
        nn--;
        goto d1;
    }
-   if (numtab[LN].val % ndf) {
+   if (numtab[LN].val % (ndf < 1 ? 1 : ndf)) {
        numtab[LN].val++;
 d1:
        un += nw * (3 + nms + ni);

but because user input is validated, the only benefit would be protection from programmers.

n-t-roff commented 5 years ago

Thank you for the bug reports and patches! Could you please check if they are applied correctly? (I had to change the commit message to fit in the 50 character limit.)

reffort commented 5 years ago

Looks like a match! Thanks.