From 9783ca9bed0cfb682e7bc76ed605aeb38571930a Mon Sep 17 00:00:00 2001
From: Addison Crump <addison.crump@cispa.de>
Date: Sat, 18 Nov 2023 16:52:00 +0100
Subject: [PATCH] Sanity checks for ctype functions (#342)

* fixup: sanity checks for ctype functions

* format

* more grep fixes

* don't check if constrained by type
---
 src/pcre2_compile.c |  4 ++++
 src/pcre2_convert.c |  8 ++++++++
 src/pcre2grep.c     | 10 +++++-----
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/src/pcre2_compile.c b/src/pcre2_compile.c
index feb5bcd..b3e4969 100644
--- a/src/pcre2_compile.c
+++ b/src/pcre2_compile.c
@@ -2194,7 +2194,11 @@ if (c == CHAR_LEFT_CURLY_BRACKET)
     {
     if (ptr >= cb->end_pattern) goto ERROR_RETURN;
     c = *ptr++;
+#if PCRE2_CODE_UNIT_WIDTH != 8
+    while (c == '_' || c == '-' || (c <= 0xff && isspace(c)))
+#else
     while (c == '_' || c == '-' || isspace(c))
+#endif
       {
       if (ptr >= cb->end_pattern) goto ERROR_RETURN;
       c = *ptr++;
diff --git a/src/pcre2_convert.c b/src/pcre2_convert.c
index 36466e4..fe396ae 100644
--- a/src/pcre2_convert.c
+++ b/src/pcre2_convert.c
@@ -540,6 +540,14 @@ Returns:   !0 => character is found in the class
 static BOOL
 convert_glob_char_in_class(int class_index, PCRE2_UCHAR c)
 {
+#if PCRE2_CODE_UNIT_WIDTH != 8
+if (c > 0xff)
+  {
+  /* ctype functions are not sane for c > 0xff */
+  return 0;
+  }
+#endif
+
 switch (class_index)
   {
   case 1: return isalnum(c);
diff --git a/src/pcre2grep.c b/src/pcre2grep.c
index 776aa28..73cf45a 100644
--- a/src/pcre2grep.c
+++ b/src/pcre2grep.c
@@ -796,7 +796,7 @@ decode_ANSI_colour(const char *cs)
 WORD result = csbi.wAttributes;
 while (*cs)
   {
-  if (isdigit(*cs))
+  if (isdigit((unsigned char)(*cs)))
     {
     int code = atoi(cs);
     if (code == 1) result |= 0x08;
@@ -810,7 +810,7 @@ while (*cs)
     else if (code >= 90 && code <= 97) result = (result & 0xF0) | BGR_RGB(code - 90) | 0x08;
     else if (code >= 100 && code <= 107) result = (result & 0x0F) | (BGR_RGB(code - 100) << 4) | 0x80;
 
-    while (isdigit(*cs)) cs++;
+    while (isdigit((unsigned char)(*cs))) cs++;
     }
   if (*cs) cs++;
   }
@@ -1989,7 +1989,7 @@ switch (*(++string))
   case '{':
   brace = TRUE;
   string++;
-  if (!isdigit(*string))  /* Syntax error: a decimal number required. */
+  if (!isdigit((unsigned char)(*string)))  /* Syntax error: a decimal number required. */
     {
     if (!callout)
       fprintf(stderr, "pcre2grep: Error in output text at offset %d: %s\n",
@@ -4036,7 +4036,7 @@ for (i = 1; i < argc; i++)
 
       if (op->type == OP_OP_NUMBER || op->type == OP_OP_NUMBERS)
         {
-        if (isdigit((unsigned char)s[1])) break;
+        if (isdigit((unsigned char)(s[1]))) break;
         }
       else   /* Check for an option with data */
         {
@@ -4520,7 +4520,7 @@ for (fn = file_lists; fn != NULL; fn = fn->next)
     {
     int frc;
     char *end = buffer + (int)strlen(buffer);
-    while (end > buffer && isspace(end[-1])) end--;
+    while (end > buffer && isspace((unsigned char)(end[-1]))) end--;
     *end = 0;
     if (*buffer != 0)
       {
-- 
2.33.0

