bug-groff
[Top][All Lists]
Advanced

[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/

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]