gbranden pushed a commit to branch master
in repository groff.

commit c220a3c3096ec62fb43a7244a8900fac9286384e
Author: G. Branden Robinson <g.branden.robin...@gmail.com>
AuthorDate: Sun Mar 16 09:32:00 2025 -0500

    [libgroff]: Fix logic error.
    
    ...when encoding characters ", \, and / as (or in) JSON strings.
    
    * src/libs/libgroff/json_encode.cpp (json_encode_char):
    * src/libs/libgroff/string.cpp (string::json_length):
    * src/libs/libgroff/symbol.cpp (symbol::json_length): Restructure
      control flow to handle them before other printable characters.
    
    Problem introduced yesterday with landing of new JSON encoding feature.
---
 ChangeLog                         | 14 ++++++++++++++
 src/libs/libgroff/json_encode.cpp | 14 +++++++-------
 src/libs/libgroff/string.cpp      |  9 ++++-----
 src/libs/libgroff/symbol.cpp      |  9 ++++-----
 4 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index cdf7d6500..b072ea14a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2025-03-16  G. Branden Robinson <g.branden.robin...@gmail.com>
+
+       [libgroff]: Fix logic error when encoding characters ", \, and /
+       as (or in) JSON strings.
+
+       * src/libs/libgroff/json_encode.cpp (json_encode_char):
+       * src/libs/libgroff/string.cpp (string::json_length):
+       * src/libs/libgroff/symbol.cpp (symbol::json_length):
+       Restructure control flow to handle them before other printable
+       characters.
+
+       Problem introduced yesterday with landing of new JSON encoding
+       feature.
+
 2025-03-15  G. Branden Robinson <g.branden.robin...@gmail.com>
 
        * src/roff/troff/input.cpp (macro:json_dump): A `macro` object
diff --git a/src/libs/libgroff/json_encode.cpp 
b/src/libs/libgroff/json_encode.cpp
index a3bc47de7..a4256771b 100644
--- a/src/libs/libgroff/json_encode.cpp
+++ b/src/libs/libgroff/json_encode.cpp
@@ -26,21 +26,21 @@ along with this program.  If not, see 
<http://www.gnu.org/licenses/>. */
 #include "json-encode.h" // json_char
 
 // Return pointer to mutable buffer representing character `c` as a JSON
-// string.  The caller must free the buffer.
+// string (without bracketing `"`s).  The caller must free the buffer.
 json_char json_encode_char(unsigned char c)
 {
   assert(c < 256);
   json_char jc;
-  // Handle the most common cases first.
-  if (csprint(c)) {
-    jc.len = 1;
-    jc.buf[0] = c;
-  }
-  else if (('"' == c) || ('\\' == c) || ('/' == c)) {
+  // These printable characters require escaping.
+  if (('"' == c) || ('\\' == c) || ('/' == c)) {
     jc.len = 2;
     jc.buf[0] = '\\';
     jc.buf[1] = c;
   }
+  else if (csprint(c)) {
+    jc.len = 1;
+    jc.buf[0] = c;
+  }
   else if ('\b' == c) {
     jc.len = 2;
     jc.buf[0] = '\\';
diff --git a/src/libs/libgroff/string.cpp b/src/libs/libgroff/string.cpp
index 739fdfe05..05f2c442c 100644
--- a/src/libs/libgroff/string.cpp
+++ b/src/libs/libgroff/string.cpp
@@ -333,15 +333,14 @@ size_t string::json_length() const
   int nextrachars = 2; // leading and trailing double quotes
   for (size_t i = 0; i < n; i++) {
     ch = p[i];
-    // Handle the most common cases first.
     if (ch < 128) {
-      if (csprint(ch))
+      // These printable characters require escaping.
+      if (('"' == ch) || ('\\' == ch) || ('/' == ch))
+       nextrachars++;
+      else if (csprint(ch))
        ;
       else
        switch (ch) {
-       case '"':
-       case '\\':
-       case '/':
        case '\b':
        case '\f':
        case '\n':
diff --git a/src/libs/libgroff/symbol.cpp b/src/libs/libgroff/symbol.cpp
index 1ed91f359..e6e1e9f29 100644
--- a/src/libs/libgroff/symbol.cpp
+++ b/src/libs/libgroff/symbol.cpp
@@ -172,15 +172,14 @@ size_t symbol::json_length() const
   int nextrachars = 2; // leading and trailing double quotes
   for (size_t i = 0; p[i] != '\0'; i++, len++) {
     ch = p[i];
-    // Handle the most common cases first.
     if (ch < 128) {
-      if (csprint(ch))
+      // These printable characters require escaping.
+      if (('"' == ch) || ('\\' == ch) || ('/' == ch))
+       nextrachars++;
+      else if (csprint(ch))
        ;
       else
        switch (ch) {
-       case '"':
-       case '\\':
-       case '/':
        case '\b':
        case '\f':
        case '\n':

_______________________________________________
groff-commit mailing list
groff-commit@gnu.org
https://lists.gnu.org/mailman/listinfo/groff-commit

Reply via email to