Closed leres closed 1 year ago
I did a quick scan and didn't find any actual problems; all other uses appear to be careful when decrementing, for example argv_uescI():
for (p = bp; len > 0; ++str, --len) {
if (IS_ESCAPE(sp, excp, *str)) {
if (--len < 1)
break;
++str;
Let me know if you'd prefer this style fix for this PR.
Better example, ex_aci():
for (t = p; len > 0 && t[0] != '\n'; ++t, --len);
if (t != p || len == 0) {
if (F_ISSET(sp, SC_EX_GLOBAL) &&
t - p == 1 && p[0] == '.') {
++t;
if (len > 0)
--len;
break;
}
I prefer
if (--len < 1)
break;
(unless you are in switch
). Variables named blen
has always been unsigned.
Thanks for the fix!
... due to
size_t
being unsigned and a loop that checks for > 0 which is always true (even when the loop variable is decremented twice).I found that I could crash nvi (both the @lichray fork and the version that comes with the base 13.1-RELEASE system) with a tags file for this macro:
I believe the trigger is the trailing '\'. The crash happens in a loop in re_tag_conv():
The extra
--len
when len is already zero is the problem.It's possible
size_t
was signed on the system nvi was developed. But at least one source claimssize_t
is "always unsigned".This PR only addresses the crash I could reproduce by making len an
int
(large enough for lines in a tags file). But there are more than 100 places where len is declared asize_t
and many/most of them have loops with len > 0 as the condition. The simple fix for the rest of these would be to changesize_t
toint
.Another way to address this would be to look for places where the loop variable is a
size_t
and the loop variable is decremented inside the loop. But that seems fragile.