[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug #66052] [troff] possible 1-byte stack overwrite, heap overread
From: |
G. Branden Robinson |
Subject: |
[bug #66052] [troff] possible 1-byte stack overwrite, heap overread |
Date: |
Sat, 31 Aug 2024 00:31:34 -0400 (EDT) |
Follow-up Comment #7, bug #66052 (group groff):
[comment #6 comment #6:]
> Looking at the commit 568beeb2efed5299868585c9bf3c700413cf1a12, isn't there
a typo where you made the change:
>
> - int num[WORD_MAX + 3];
> + int num[WORD_MAX + 2 + 1];
>
> Shouldn't it be:
>
> - int num[WORD_MAX + 3];
> + int num[WORD_MAX + 3 + 1];
>
> Thanks for checking it out.
Hi Lukas.
I don't think so. As part of the next commit after that, I annotated the
function to try to make clearer what's going on.
Here's what it looks like now.
of _The TeXbook_ is useful background for the following.
void hyphenate(hyphen_list *h, unsigned flags)
{
if (!current_language)
return;
while (h) {
while (h && (0 == h->hyphenation_code))
h = h->next;
int len = 0;
// Locate hyphenable points within a (subset of) an input word.
//
// We first look up the word in the environment's hyphenation
// exceptions dictionary; its keys are C strings, so the buffer
// `hbuf` that holds our word needs to be null terminated and we
// allocate a byte for that. If the lookup fails, we apply the
// hyphenation patterns, which require that the word be bracketed at
// each end with a dot ('.'), so we allocate two further bytes.
//
// `hbuf` can be thought of as a mapping of the letters of the input
// word to the hyphenation codes that correspond to each letter.
// The hyphenation codes are normalized; "AbBoT" becomes "abbot".
//
// We can hyphenate words longer than WORD_MAX, but WORD_MAX is the
// maximum size of the "window" inside a word within which we apply
// the hyphenation patterns to determine a break point.
char hbuf[WORD_MAX + 2 + 1];
(void) memset(hbuf, '\0', sizeof hbuf);
char *bufp = hbuf + 1;
hyphen_list *tem;
for (tem = h; tem && len < WORD_MAX; tem = tem->next) {
if (tem->hyphenation_code != 0)
bufp[len++] = tem->hyphenation_code;
else
break;
}
hyphen_list *nexth = tem;
if (len >= 2) {
// Check hyphenation exceptions defined with `hw` request.
assert((bufp + len) < (hbuf + sizeof hbuf));
bufp[len] = '\0';
unsigned char *pos = static_cast<unsigned char *>(
current_language->exceptions.lookup(bufp));
if (pos != 0 /* nullptr */) {
int j = 0;
int i = 1;
for (tem = h; tem != 0 /* nullptr */; tem = tem->next, i++)
if (pos[j] == i) {
tem->is_hyphen = true;
j++;
}
}
else {
// Check `\hyphenation' entries from pattern files; such entries
// are marked with a trailing space.
assert((hbuf + len + 1) < (hbuf + sizeof hbuf));
bufp[len] = ' ';
bufp[len + 1] = '\0';
pos = static_cast<unsigned char *>(
current_language->exceptions.lookup(bufp));
if (pos != 0 /* nullptr */) {
int j = 0;
int i = 1;
tem = h;
if (pos[j] == i) {
if (flags & HYPHEN_FIRST_CHAR)
tem->is_hyphen = true;
j++;
}
tem = tem->next;
i++;
if (pos[j] == i) {
if (!(flags & HYPHEN_NOT_FIRST_CHARS))
tem->is_hyphen = true;
j++;
}
tem = tem->next;
i++;
if (!(flags & HYPHEN_LAST_CHAR))
--len;
if (flags & HYPHEN_NOT_LAST_CHARS)
--len;
for (; i < len && tem; tem = tem->next, i++)
if (pos[j] == i) {
tem->is_hyphen = true;
j++;
}
}
else {
hbuf[0] = hbuf[len + 1] = '.';
int num[WORD_MAX + 2 + 1];
(void) memset(num, 0, sizeof num);
current_language->patterns.hyphenate(hbuf, len + 2, num);
// The position of a hyphenation point gets marked with an odd
// number. Example:
//
// hbuf: . h e l p f u l .
// num: 0 0 0 2 4 3 0 0 0 0
if (!(flags & HYPHEN_FIRST_CHAR))
num[2] = 0;
if (flags & HYPHEN_NOT_FIRST_CHARS)
num[3] = 0;
if (flags & HYPHEN_LAST_CHAR)
++len;
if (flags & HYPHEN_NOT_LAST_CHARS)
--len;
int i;
for (i = 2, tem = h; i < len && tem; tem = tem->next, i++)
if (num[i] & 1)
tem->is_hyphen = true;
}
}
}
h = nexth;
}
}
_______________________________________________________
Reply to this item at:
<https://savannah.gnu.org/bugs/?66052>
_______________________________________________
Message sent via Savannah
https://savannah.gnu.org/
signature.asc
Description: PGP signature
- [bug #66052] Possible OVERRUN on two arrays in roff/troff, Lukas, 2024/08/01
- [bug #66052] [troff] possible 1-byte stack and heap overruns, G. Branden Robinson, 2024/08/01
- [bug #66052] [troff] possible 1-byte stack and heap overruns, G. Branden Robinson, 2024/08/07
- [bug #66052] [troff] possible 1-byte stack and heap overruns, G. Branden Robinson, 2024/08/07
- [bug #66052] [troff] possible 1-byte stack overwrite, heap overread, G. Branden Robinson, 2024/08/07
- [bug #66052] [troff] possible 1-byte stack overwrite, heap overread, G. Branden Robinson, 2024/08/07
- [bug #66052] [troff] possible 1-byte stack overwrite, heap overread, G. Branden Robinson, 2024/08/08
- [bug #66052] [troff] possible 1-byte stack overwrite, heap overread, G. Branden Robinson, 2024/08/09
- [bug #66052] [troff] possible 1-byte stack overwrite, heap overread, Lukas Javorsky, 2024/08/21
- [bug #66052] [troff] possible 1-byte stack overwrite, heap overread,
G. Branden Robinson <=