gbranden pushed a commit to branch master
in repository groff.

commit fc727f4435e1ab290870ee7951132a66bb148b5d
Author: G. Branden Robinson <[email protected]>
AuthorDate: Thu Aug 1 16:45:35 2024 -0500

    [troff]: Validate `hcode` request arguments more.
    
    * src/roff/troff/input.cpp (set_hyphenation_code): Do more input
      validation of `hcode` request arguments.  Handle case where an
      argument is an escape sequence (but not a special character) ourselves
      instead of delegating it to `token::get_char()`.  Throw errors (and
      stop processing arguments) when (1) the destination character is a
      numeral; (2) the destination character is a (non-special-character)
      escape sequence; (3) the source character is a numeral; or (4) the
      source character is a (non-special-character) escape sequence.
    
    * doc/groff.texi.in (Manipulating Hyphenation) <hcode>:
    * man/groff_diff.7.man (New requests) <hcode>: Document that the request
      aborts processing its arguments upon encountering an invalid one.
    
    Continues <https://savannah.gnu.org/bugs/?66040>.  Thanks to Dave Kemper
    for further discussion.
    
    $ nl hcode.groff
         1  .hcode
         2  .hcode \:
         3  .hcode a
         4  .hcode 0 b
         5  .hcode c\:
         6  .hcode \['A] \['a]
         7  .hcode d 0
         8  .hcode eE
         9  .hcode f F
        10  .hcode g G\" This is my comment.
        11  .hcode \['i] i
        12  .hcode \['o] \['o]
        13  .hcode \['u] u
        14  .hcode \['U] \['u]
    $ ./build/test-groff -T utf8 -ww hcode.groff
    troff:hcode.groff:1: warning: hyphenation code configuration request 
expects arguments
    troff:hcode.groff:2: error: expected ordinary or special character, got an 
escaped ':'
    troff:hcode.groff:3: error: hyphenation codes must be specified in pairs
    troff:hcode.groff:4: error: cannot apply a hyphenation code to a numeral
    troff:hcode.groff:5: error: expected ordinary or special character, got an 
escaped ':'
    troff:hcode.groff:6: error: second member of hyphenation code pair must be 
an ordinary character
    troff:hcode.groff:7: error: cannot use the hyphenation code of a numeral
    troff:hcode.groff:12: error: second member of hyphenation code pair must be 
an ordinary character
    troff:hcode.groff:14: error: second member of hyphenation code pair must be 
an ordinary character
---
 ChangeLog                | 20 ++++++++++++++++++
 doc/groff.texi.in        |  3 ++-
 man/groff_diff.7.man     |  4 ++++
 src/roff/troff/input.cpp | 53 ++++++++++++++++++++++++++++++------------------
 4 files changed, 59 insertions(+), 21 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b77e4d432..5f117ac24 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2024-08-01  G. Branden Robinson <[email protected]>
+
+       * src/roff/troff/input.cpp (set_hyphenation_code): Do more input
+       validation of `hcode` request arguments.  Handle case where an
+       argument is an escape sequence (but not a special character)
+       ourselves instead of delegating it to `token::get_char()`.
+       Throw errors (and stop processing arguments) when {1} the
+       destination character is a numeral; {2} the destination
+       character is a (non-special-character) escape sequence; {3} the
+       source character is a numeral; or {4} the source character is a
+       {non-special-character} escape sequence.
+
+       * doc/groff.texi.in (Manipulating Hyphenation) <hcode>:
+       * man/groff_diff.7.man (New requests) <hcode>: Document that the
+       request aborts processing its arguments upon encountering an
+       invalid one.
+
+       Continues <https://savannah.gnu.org/bugs/?66040>.  Thanks to
+       Dave Kemper for further discussion.
+
 2024-08-01  G. Branden Robinson <[email protected]>
 
        * doc/groff.texi.in (Manipulating Hyphenation) <hcode>:
diff --git a/doc/groff.texi.in b/doc/groff.texi.in
index bbf35d3c4..f77025250 100644
--- a/doc/groff.texi.in
+++ b/doc/groff.texi.in
@@ -8988,7 +8988,8 @@ that of @var{src1}, and so on.  @var{dst1} must be an 
ordinary character
 ordinary character (other than a numeral).  Assigning the code of an
 ordinary character code to itself effectively creates a unique
 hyphenation code (which can then be copied to others).  @code{hcode}
-ignores spaces between arguments.
+ignores spaces between arguments.  If any argument is invalid,
+@code{hcode} reports an error and stops reading them.
 
 For example, the following @code{hcode} requests are necessary to assign
 hyphenation codes to the letters @samp{�������}, needed for German.
diff --git a/man/groff_diff.7.man b/man/groff_diff.7.man
index e3ec772f7..32f4dc0c3 100644
--- a/man/groff_diff.7.man
+++ b/man/groff_diff.7.man
@@ -2628,6 +2628,10 @@ effectively creates a unique hyphenation code
 .B hcode
 ignores spaces between arguments.
 .
+If any argument is invalid,
+.B hcode
+reports an error and stops reading them.
+.
 .
 .IP
 For automatic hyphenation to work,
diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp
index 615cd3820..c5eaa52de 100644
--- a/src/roff/troff/input.cpp
+++ b/src/roff/troff/input.cpp
@@ -7284,37 +7284,50 @@ static void set_hyphenation_codes()
     return;
   }
   while (!tok.is_newline() && !tok.is_eof()) {
-    charinfo *ci = tok.get_char(true /* required */);
-    // If we got back some nonsense like a non-character escape
-    // sequence, get_char() will have diagnosed it.
-    if (0 /* nullptr */ == ci)
+    unsigned char cdst = tok.ch();
+    if (csdigit(cdst)) {
+      error("cannot apply a hyphenation code to a numeral");
       break;
+    }
+    charinfo *cidst = tok.get_char();
+    if (0 == cdst) { // destination character is special
+      if (0 /* nullptr */ == cidst) {
+       error("expected ordinary or special character, got %1",
+             tok.description());
+       break;
+      }
+    }
     tok.next();
     tok.skip();
     if (tok.is_newline() || tok.is_eof()) {
       error("hyphenation codes must be specified in pairs");
       break;
     }
-    charinfo *ci2 = tok.get_char(true /* required */);
-    unsigned char c = tok.ch();
-    if (0 == c) {
-      if (0 /* nullptr */ == ci2)
-       break;
-      if (0 == ci2->get_hyphenation_code()) {
-       error("second member of hyphenation code pair must be an"
-             " ordinary character");
+    unsigned char csrc = tok.ch();
+    if (csdigit(csrc)) {
+      error("cannot use the hyphenation code of a numeral");
+      break;
+    }
+    unsigned char new_code = 0; // TODO: int
+    charinfo *cisrc = tok.get_char();
+    if (csrc != 0)
+      new_code = csrc;
+    else {
+      if (0 /* nullptr */ == cisrc) {
+       error("expected ordinary or special character, got %1",
+             tok.description());
        break;
       }
-    }
-    // TODO: What if you want to unset a hyphenation code?  Accept 0?
-    if (csdigit(c)) {
-      error("hyphenation code cannot be digit");
+      // source character is special
+      error("second member of hyphenation code pair must be an"
+           " ordinary character");
       break;
+      new_code = cisrc->get_hyphenation_code();
     }
-    ci->set_hyphenation_code(c);
-    if (ci->get_translation()
-       && ci->get_translation()->get_translation_input())
-      ci->get_translation()->set_hyphenation_code(c);
+    cidst->set_hyphenation_code(new_code);
+    if (cidst->get_translation()
+       && cidst->get_translation()->get_translation_input())
+      cidst->get_translation()->set_hyphenation_code(new_code);
     tok.next();
     tok.skip();
   }

_______________________________________________
Groff-commit mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/groff-commit

Reply via email to