Avoid ctype(3) abuses

Leonardo Taccari <[email protected]> Mon, 12 Jan 2026 11:05:17 +0100
Newsgroups gmane.comp.web.dillo.devel
Message-ID <[email protected]>
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <12188.1768212317.1@boh>

Hello!

Most ctype(3) functions usage abuses an undefined behavior of passing
values outside integers outside EOF or the range representable as
unsigned char.

On NetBSD 11 and newer such incorrect behaviors crashes applications
violating that and due that Dillo easily crash by just visiting, e.g.
<https://www.NetBSD.org/>.

For possible further information please give a look to
<https://man.NetBSD.org/ctype.3#CAVEATS>.


I have grep-ed all such uses and added the relevant cast to uchar_t
similar to other ctype(3) calls already present and in that way I can
also confirm that Dillo no longer crashes.

Attached in this email you can find a patch to address that.


Thank you!

------- =_aaaaaaaaaa0
Content-Type: text/x-diff; charset="us-ascii";
	name="0001-Avoid-ctype-3-abuses.patch"
Content-Description: 0001-Avoid-ctype-3-abuses.patch
Content-Disposition: attachment; filename="0001-Avoid-ctype-3-abuses.patch"
Content-Transfer-Encoding: quoted-printable

=46rom f7a91f505a86caa91e3ab8eb61b41ed046071697 Mon Sep 17 00:00:00 2001
From: Leonardo Taccari <[email protected]>
Date: Tue, 6 Jan 2026 18:04:50 +0100
Subject: [PATCH] Avoid ctype(3) abuses

Valid argument of ctype(3) functions must be either EOF or non-negative
value within the range representable as unsigned char.  Invalid values
leads to undefined behavior.

Cast all such uses to avoid that.

Noticed by running dillo on NetBSD where dillo crashes due such
abuses.
---
 dlib/dlib.c          |  2 +-
 dpi/bookmarks.c      | 26 ++++++++++----------
 dpi/cookies.c        | 18 +++++++-------
 dpi/downloads.cc     | 10 ++++----
 dpi/dpiutil.c        |  6 ++---
 dpid/dpidc.c         |  2 +-
 dpip/dpip.c          |  2 +-
 dw/findtext.hh       |  4 +--
 dw/fltkui.cc         |  4 +--
 dw/textblock.cc      |  8 +++---
 src/IO/dpi.c         |  2 +-
 src/IO/http.c        |  2 +-
 src/IO/tls_openssl.c |  8 +++---
 src/cssparser.cc     | 18 +++++++-------
 src/hsts.c           |  2 +-
 src/html.cc          | 58 ++++++++++++++++++++++----------------------
 src/keys.cc          |  4 +--
 src/table.cc         |  2 +-
 test/unit/cookies.c  |  2 +-
 19 files changed, 90 insertions(+), 90 deletions(-)

diff --git a/dlib/dlib.c b/dlib/dlib.c
index ed967b3a..7fbe8892 100644
--- a/dlib/dlib.c
+++ b/dlib/dlib.c
@@ -525,7 +525,7 @@ const char *dStr_printable(Dstr *in, int maxlen)
       out =3D dStr_sized_new(in->len);
 =

    for (i =3D 0; (i < in->len) && (out->len < maxlen); ++i) {
-      if (isprint(in->str[i]) || (in->str[i] =3D=3D '\n')) {
+      if (isprint((uchar_t)in->str[i]) || (in->str[i] =3D=3D '\n')) {
          dStr_append_c(out, in->str[i]);
       } else {
          dStr_append_l(out, "\\x", 2);
diff --git a/dpi/bookmarks.c b/dpi/bookmarks.c
index 68b5edfb..fdf8950d 100644
--- a/dpi/bookmarks.c
+++ b/dpi/bookmarks.c
@@ -338,8 +338,8 @@ static void Unencode_str(char *e_str)
             *p =3D '\n';
             e +=3D 5;
          } else {
-            *p =3D (isdigit(e[1]) ? (e[1] - '0') : (e[1] - 'A' + 10)) * 1=
6 +
-                 (isdigit(e[2]) ? (e[2] - '0') : (e[2] - 'A' + 10));
+            *p =3D (isdigit((uchar_t)e[1]) ? (e[1] - '0') : (e[1] - 'A' +=
 10)) * 16 +
+                 (isdigit((uchar_t)e[2]) ? (e[2] - '0') : (e[2] - 'A' + 1=
0));
             e +=3D 2;
          }
       } else {
@@ -807,11 +807,11 @@ static void Bmsrv_count_urls_and_sections(char *url,=
 int *n_sec, int *n_url)
    *n_sec =3D *n_url =3D 0;
    if ((p =3D strchr(url, '?'))) {
       for (q =3D p; (q =3D strstr(q, "&url")); ++q) {
-         for (i =3D 0; isdigit(q[4+i]); ++i);
+         for (i =3D 0; isdigit((uchar_t)q[4+i]); ++i);
          *n_url +=3D (q[4+i] =3D=3D '=3D') ? 1 : 0;
       }
       for (q =3D p; (q =3D strstr(q, "&s")); ++q) {
-         for (i =3D 0; isdigit(q[2+i]); ++i);
+         for (i =3D 0; isdigit((uchar_t)q[2+i]); ++i);
          *n_sec +=3D (q[2+i] =3D=3D '=3D') ? 1 : 0;
       }
    }
@@ -972,7 +972,7 @@ static int Bmsrv_send_modify_update(Dsh *sh, char *url=
)
       /* send items here */
       p =3D strchr(url1, '?');
       for (q =3D p; (q =3D strstr(q, "&s")); ++q) {
-         for (i =3D 0; isdigit(q[2+i]); ++i);
+         for (i =3D 0; isdigit((uchar_t)q[2+i]); ++i);
          if (q[2+i] =3D=3D '=3D') {
             key =3D strtol(q + 2, NULL, 10);
             if ((sec_node =3D Bms_get_sec(key))) {
@@ -992,7 +992,7 @@ static int Bmsrv_send_modify_update(Dsh *sh, char *url=
)
       /* send items here */
       p =3D strchr(url1, '?');
       for (q =3D p; (q =3D strstr(q, "&url")); ++q) {
-         for (i =3D 0; isdigit(q[4+i]); ++i);
+         for (i =3D 0; isdigit((uchar_t)q[4+i]); ++i);
          if (q[4+i] =3D=3D '=3D') {
             key =3D strtol(q + 4, NULL, 10);
             bm_node =3D Bms_get(key);
@@ -1060,7 +1060,7 @@ static int Bmsrv_modify_delete(char *url)
    /* Remove marked sections */
    p =3D strchr(url, '?');
    for (ns =3D 0; (p =3D strstr(p, "&s")); ++p) {
-      if (isdigit(p[2])) {
+      if (isdigit((uchar_t)p[2])) {
          key =3D strtol(p + 2, NULL, 10);
          Bms_sec_del(key);
          ++ns;
@@ -1070,7 +1070,7 @@ static int Bmsrv_modify_delete(char *url)
    /* Remove marked urls */
    p =3D strchr(url, '?');
    for (nb =3D 0; (p =3D strstr(p, "&url")); ++p) {
-      if (isdigit(p[4])) {
+      if (isdigit((uchar_t)p[4])) {
          key =3D strtol(p + 4, NULL, 10);
          Bms_del(key);
          ++nb;
@@ -1105,7 +1105,7 @@ static int Bmsrv_modify_move(char *url)
 =

    /* get target section */
    for (p =3D url; (p =3D strstr(p, "&s")); ++p) {
-      if (isdigit(p[2])) {
+      if (isdigit((uchar_t)p[2])) {
          section =3D strtol(p + 2, NULL, 10);
          break;
       }
@@ -1116,7 +1116,7 @@ static int Bmsrv_modify_move(char *url)
    /* move marked urls */
    p =3D strchr(url, '?');
    for (n =3D 0; (p =3D strstr(p, "&url")); ++p) {
-      if (isdigit(p[4])) {
+      if (isdigit((uchar_t)p[4])) {
          key =3D strtol(p + 4, NULL, 10);
          Bms_move(key, section);
          ++n;
@@ -1145,7 +1145,7 @@ static int Bmsrv_modify_update(char *url)
    p =3D strchr(url, '?');
    for (  ; (p =3D strstr(p, "s")); ++p) {
       if (p[-1] =3D=3D '&' || p[-1] =3D=3D '?' ) {
-         for (i =3D 0; isdigit(p[1 + i]); ++i);
+         for (i =3D 0; isdigit((uchar_t)p[1 + i]); ++i);
          if (i && p[1 + i] =3D=3D '=3D') {
             /* we have a title/key to change */
             key =3D strtol(p + 1, NULL, 10);
@@ -1164,7 +1164,7 @@ static int Bmsrv_modify_update(char *url)
    p =3D strchr(url, '?');
    for (  ; (p =3D strstr(p, "title")); ++p) {
       if (p[-1] =3D=3D '&' || p[-1] =3D=3D '?' ) {
-         for (i =3D 0; isdigit(p[5 + i]); ++i);
+         for (i =3D 0; isdigit((uchar_t)p[5 + i]); ++i);
          if (i && p[5 + i] =3D=3D '=3D') {
             /* we have a title/key to change */
             key =3D strtol(p + 5, NULL, 10);
@@ -1229,7 +1229,7 @@ static int Bmsrv_modify_add_url(Dsh *sh, char *s_url=
)
    if (sh =3D=3D NULL) {
       /* look for section */
       for (q =3D s_url; (q =3D strstr(q, "&s")); ++q) {
-         for (i =3D 0; isdigit(q[2+i]); ++i);
+         for (i =3D 0; isdigit((uchar_t)q[2+i]); ++i);
          if (q[2+i] =3D=3D '=3D')
             section =3D strtol(q + 2, NULL, 10);
       }
diff --git a/dpi/cookies.c b/dpi/cookies.c
index f629768e..df6bc5a0 100644
--- a/dpi/cookies.c
+++ b/dpi/cookies.c
@@ -487,14 +487,14 @@ static int Cookies_get_timefield(const char **str)
    int n;
    const char *s =3D *str;
 =

-   if (!isdigit(*s))
+   if (!isdigit((uchar_t)*s))
       return -1;
 =

    n =3D *(s++) - '0';
-   if (isdigit(*s)) {
+   if (isdigit((uchar_t)*s)) {
       n *=3D 10;
       n +=3D *(s++) - '0';
-      if (isdigit(*s))
+      if (isdigit((uchar_t)*s))
          return -1;
    }
    *str =3D s;
@@ -550,24 +550,24 @@ static bool_t Cookies_get_year(struct tm *tm, const =
char **str)
    int n;
    const char *s =3D *str;
 =

-   if (isdigit(*s))
+   if (isdigit((uchar_t)*s))
       n =3D *(s++) - '0';
    else
       return FALSE;
-   if (isdigit(*s)) {
+   if (isdigit((uchar_t)*s)) {
       n *=3D 10;
       n +=3D *(s++) - '0';
    } else
       return FALSE;
-   if (isdigit(*s)) {
+   if (isdigit((uchar_t)*s)) {
       n *=3D 10;
       n +=3D *(s++) - '0';
    }
-   if (isdigit(*s)) {
+   if (isdigit((uchar_t)*s)) {
       n *=3D 10;
       n +=3D *(s++) - '0';
    }
-   if (isdigit(*s)) {
+   if (isdigit((uchar_t)*s)) {
       /* Sorry, users of prehistoric software in the year 10000! */
       return FALSE;
    }
@@ -936,7 +936,7 @@ static CookieData_t *Cookies_parse(char *cookie_str, c=
onst char *server_date)
          cookie->domain =3D value;
       } else if (dStrAsciiCasecmp(attr, "Max-Age") =3D=3D 0) {
          value =3D Cookies_parse_value(&str);
-         if (isdigit(*value) || *value =3D=3D '-') {
+         if (isdigit((uchar_t)*value) || *value =3D=3D '-') {
             long age;
             time_t now =3D time(NULL);
             struct tm *tm =3D gmtime(&now);
diff --git a/dpi/downloads.cc b/dpi/downloads.cc
index 69e04f8f..7f2a8105 100644
--- a/dpi/downloads.cc
+++ b/dpi/downloads.cc
@@ -513,7 +513,7 @@ void DLItem::log_text_add(const char *buf, ssize_t st)
       case ST_newline:
          if (*p =3D=3D ' ') {
             log_state =3D ST_discard;
-         } else if (isdigit(*p)) {
+         } else if (isdigit((uchar_t)*p)) {
             *q++ =3D *p; log_state =3D ST_number;
          } else if (*p =3D=3D '\n') {
             *q++ =3D *p;
@@ -522,10 +522,10 @@ void DLItem::log_text_add(const char *buf, ssize_t s=
t)
          }
          break;
       case ST_number:
-         if (isdigit(*q++ =3D *p)) {
+         if (isdigit((uchar_t)(*q++ =3D *p))) {
             // keep here
          } else if (*p =3D=3D 'K') {
-            for (--q; isdigit(q[-1]); --q) ; =

+            for (--q; isdigit((uchar_t)q[-1]); --q) ; =

             log_state =3D ST_discard;
          } else {
             log_state =3D ST_copy;
@@ -549,9 +549,9 @@ void DLItem::log_text_add(const char *buf, ssize_t st)
    // Now scan for the length of the file
    if (total_bytesize =3D=3D -1) {
       p =3D strstr(log_text, "\nLength: ");
-      if (p && isdigit(p[9]) && strchr(p + 9, ' ')) {
+      if (p && isdigit((uchar_t)p[9]) && strchr(p + 9, ' ')) {
          for (p +=3D 9, d =3D &num[0]; *p !=3D ' '; ++p)
-            if (isdigit(*p))
+            if (isdigit((uchar_t)*p))
                *d++ =3D *p;
          *d =3D 0;
          total_bytesize =3D strtol (num, NULL, 10);
diff --git a/dpi/dpiutil.c b/dpi/dpiutil.c
index 45100be2..009ec5c9 100644
--- a/dpi/dpiutil.c
+++ b/dpi/dpiutil.c
@@ -67,10 +67,10 @@ char *Unescape_uri_str(const char *s)
 =

    if (strchr(s, '%')) {
       for (p =3D buf; (*p =3D *s); ++s, ++p) {
-         if (*p =3D=3D '%' && isxdigit(s[1]) && isxdigit(s[2])) {
-            *p =3D (isdigit(s[1]) ? (s[1] - '0')
+         if (*p =3D=3D '%' && isxdigit((uchar_t)s[1]) && isxdigit((uchar_=
t)s[2])) {
+            *p =3D (isdigit((uchar_t)s[1]) ? (s[1] - '0')
                                 : D_ASCII_TOUPPER(s[1]) - 'A' + 10) * 16;
-            *p +=3D isdigit(s[2]) ? (s[2] - '0')
+            *p +=3D isdigit((uchar_t)s[2]) ? (s[2] - '0')
                                 : D_ASCII_TOUPPER(s[2]) - 'A' + 10;
             s +=3D 2;
          }
diff --git a/dpid/dpidc.c b/dpid/dpidc.c
index f9e579b2..81376778 100644
--- a/dpid/dpidc.c
+++ b/dpid/dpidc.c
@@ -59,7 +59,7 @@ static int Dpi_read_comm_keys(int *port)
       MSG_ERR("[Dpi_read_comm_keys] empty file: %s\n", fname);
    } else {
       *port =3D strtol(rcline, &tail, 10);
-      for (i =3D 0; *tail && isxdigit(tail[i+1]); ++i)
+      for (i =3D 0; *tail && isxdigit((uchar_t)tail[i+1]); ++i)
          SharedKey[i] =3D tail[i+1];
       SharedKey[i] =3D 0;
       ret =3D 1;
diff --git a/dpip/dpip.c b/dpip/dpip.c
index 066d82e9..751480f3 100644
--- a/dpip/dpip.c
+++ b/dpip/dpip.c
@@ -220,7 +220,7 @@ int a_Dpip_check_auth(const char *auth_tag)
    } else {
       port =3D strtol(rcline, &tail, 10);
       if (tail && port !=3D 0) {
-         for (i =3D 0; *tail && isxdigit(tail[i+1]); ++i)
+         for (i =3D 0; *tail && isxdigit((uchar_t)tail[i+1]); ++i)
             SharedSecret[i] =3D tail[i+1];
          SharedSecret[i] =3D 0;
          if (strcmp(msg, SharedSecret) =3D=3D 0)
diff --git a/dw/findtext.hh b/dw/findtext.hh
index 1923acce..0d1a4bb0 100644
--- a/dw/findtext.hh
+++ b/dw/findtext.hh
@@ -66,8 +66,8 @@ private:
    bool search0 (bool backwards, bool firstTrial);
 =

    inline static bool charsEqual (char c1, char c2, bool caseSens)
-   { return caseSens ? c1 =3D=3D c2 : tolower (c1) =3D=3D tolower (c2) ||
-      (isspace (c1) && isspace (c2)); }
+   { return caseSens ? c1 =3D=3D c2 : tolower ((uchar_t)c1) =3D=3D tolowe=
r ((uchar_t)c2) ||
+      (isspace ((uchar_t)c1) && isspace ((uchar_t)c2)); }
 =

 public:
    FindtextState ();
diff --git a/dw/fltkui.cc b/dw/fltkui.cc
index 11fbb883..a82c6ef6 100644
--- a/dw/fltkui.cc
+++ b/dw/fltkui.cc
@@ -366,14 +366,14 @@ int CustChoice::handle(int e)
       if (k =3D=3D FL_Enter || k =3D=3D FL_Down) {
          return Fl_Choice::handle(FL_PUSH); // activate menu
 =

-      } else if (isalnum(k)) { // try key as shortcut to menuitem
+      } else if (isalnum((uchar_t)k)) { // try key as shortcut to menuite=
m
          int t =3D value()+1 >=3D size() ? 0 : value()+1;
          while (t !=3D value()) {
              const Fl_Menu_Item *mi =3D &(menu()[t]);
              if (mi->submenu()) // submenu?
                 ;
              else if (mi->label() && mi->active()) { // menu item?
-                if (k =3D=3D tolower(mi->label()[0])) {
+                if (k =3D=3D tolower((uchar_t)mi->label()[0])) {
                    value(mi);
                    return 1; // Let FLTK know we used this key
                 }
diff --git a/dw/textblock.cc b/dw/textblock.cc
index a1cbf2a3..dee1c874 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -1238,14 +1238,14 @@ void Textblock::drawText(core::View *view, core::s=
tyle::Style *style,
                bool initial_seen =3D false;
 =

                for (int i =3D 0; i < start; i++)
-                  if (!ispunct(text[i]))
+                  if (!ispunct((uchar_t)text[i]))
                      initial_seen =3D true;
                if (initial_seen)
                   break;
 =

                int after =3D 0;
                text +=3D start;
-               while (ispunct(text[after]))
+               while (ispunct((uchar_t)text[after]))
                   after++;
                if (text[after])
                   after =3D layout->nextGlyph(text, after);
@@ -1931,7 +1931,7 @@ int Textblock::textWidth(const char *text, int start=
, int len,
                bool initial_seen =3D false;
 =

                for (int i =3D 0; i < start; i++)
-                  if (!ispunct(text[i]))
+                  if (!ispunct((uchar_t)text[i]))
                      initial_seen =3D true;
                if (initial_seen) {
                   ret =3D layout->textWidth(style->font, text+start, len)=
;
@@ -1939,7 +1939,7 @@ int Textblock::textWidth(const char *text, int start=
, int len,
                   int after =3D 0;
 =

                   text +=3D start;
-                  while (ispunct(text[after]))
+                  while (ispunct((uchar_t)text[after]))
                      after++;
                   if (text[after])
                      after =3D layout->nextGlyph(text, after);
diff --git a/src/IO/dpi.c b/src/IO/dpi.c
index 6729b011..40c99c23 100644
--- a/src/IO/dpi.c
+++ b/src/IO/dpi.c
@@ -405,7 +405,7 @@ static int Dpi_read_comm_keys(int *port)
       MSG_ERR("[Dpi_read_comm_keys] empty file: %s\n", fname);
    } else {
       *port =3D strtol(rcline, &tail, 10);
-      for (i =3D 0; *tail && isxdigit(tail[i+1]); ++i)
+      for (i =3D 0; *tail && isxdigit((uchar_t)tail[i+1]); ++i)
          SharedKey[i] =3D tail[i+1];
       SharedKey[i] =3D 0;
       ret =3D 1;
diff --git a/src/IO/http.c b/src/IO/http.c
index f5d98df8..15763a65 100644
--- a/src/IO/http.c
+++ b/src/IO/http.c
@@ -709,7 +709,7 @@ static char *Http_get_connect_str(const DilloUrl *url)
    dstr =3D dStr_new("");
    auth1 =3D URL_AUTHORITY(url);
    auth_len =3D strlen(auth1);
-   if (auth_len > 0 && !isdigit(auth1[auth_len - 1]))
+   if (auth_len > 0 && !isdigit((uchar_t)auth1[auth_len - 1]))
       /* if no port number, add HTTPS port */
       auth2 =3D dStrconcat(auth1, ":443", NULL);
    else
diff --git a/src/IO/tls_openssl.c b/src/IO/tls_openssl.c
index 3345a0dc..b057c0fb 100644
--- a/src/IO/tls_openssl.c
+++ b/src/IO/tls_openssl.c
@@ -577,13 +577,13 @@ static bool_t pattern_match (const char *pattern, co=
nst char *string)
 =

   const char *p =3D pattern, *n =3D string;
   char c;
-  for (; (c =3D tolower (*p++)) !=3D '\0'; n++)
+  for (; (c =3D tolower ((uchar_t)*p++)) !=3D '\0'; n++)
     if (c =3D=3D '*')
       {
-        for (c =3D tolower (*p); c =3D=3D '*'; c =3D tolower (*++p))
+        for (c =3D tolower ((uchar_t)*p); c =3D=3D '*'; c =3D tolower ((u=
char_t)*++p))
           ;
         for (; *n !=3D '\0'; n++)
-          if (tolower (*n) =3D=3D c && pattern_match (p, n))
+          if (tolower ((uchar_t)*n) =3D=3D c && pattern_match (p, n))
             return TRUE;
 #ifdef ASTERISK_EXCLUDES_DOT
           else if (*n =3D=3D '.')
@@ -593,7 +593,7 @@ static bool_t pattern_match (const char *pattern, cons=
t char *string)
       }
     else
       {
-        if (c !=3D tolower (*n))
+        if (c !=3D tolower ((uchar_t)*n))
           return FALSE;
       }
   return *n =3D=3D '\0';
diff --git a/src/cssparser.cc b/src/cssparser.cc
index 065eb624..7c6765a3 100644
--- a/src/cssparser.cc
+++ b/src/cssparser.cc
@@ -530,7 +530,7 @@ void CssParser::nextToken()
 =

    while (true) {
       c =3D getChar();
-      if (isspace(c)) {                    // ignore whitespace
+      if (isspace((uchar_t)c)) {                    // ignore whitespace
          spaceSeparated =3D true;
       } else if (skipString(c, "/*")) {    // ignore comments
          do {
@@ -550,7 +550,7 @@ void CssParser::nextToken()
       c =3D getChar();
    }
 =

-   if (isdigit(c)) {
+   if (isdigit((uchar_t)c)) {
       ttype =3D CSS_TK_DECINT;
       do {
          if (i < maxStrLen - 1) {
@@ -567,7 +567,7 @@ void CssParser::nextToken()
 =

    if (c =3D=3D '.') {
       c =3D getChar();
-      if (isdigit(c)) {
+      if (isdigit((uchar_t)c)) {
          ttype =3D CSS_TK_FLOAT;
          if (i < maxStrLen - 1)
             tval[i++] =3D '.';
@@ -576,7 +576,7 @@ void CssParser::nextToken()
                tval[i++] =3D c;
             /* else silently truncated */
             c =3D getChar();
-         } while (isdigit(c));
+         } while (isdigit((uchar_t)c));
 =

          ungetChar();
          tval[i] =3D 0;
@@ -604,13 +604,13 @@ void CssParser::nextToken()
       c =3D getChar();
    }
 =

-   if (isalpha(c) || c =3D=3D '_' || c =3D=3D '-') {
+   if (isalpha((uchar_t)c) || c =3D=3D '_' || c =3D=3D '-') {
       ttype =3D CSS_TK_SYMBOL;
 =

       tval[0] =3D c;
       i =3D 1;
       c =3D getChar();
-      while (isalnum(c) || c =3D=3D '_' || c =3D=3D '-') {
+      while (isalnum((uchar_t)c) || c =3D=3D '_' || c =3D=3D '-') {
          if (i < maxStrLen - 1) {
             tval[i] =3D c;
             i++;
@@ -633,13 +633,13 @@ void CssParser::nextToken()
       while (c !=3D EOF && c !=3D c1) {
          if (c =3D=3D '\\') {
             d =3D getChar();
-            if (isxdigit(d)) {
+            if (isxdigit((uchar_t)d)) {
                /* Read hex Unicode char. (Actually, strings are yet only =
8
                 * bit.) */
                hexbuf[0] =3D d;
                j =3D 1;
                d =3D getChar();
-               while (j < 4 && isxdigit(d)) {
+               while (j < 4 && isxdigit((uchar_t)d)) {
                   hexbuf[j] =3D d;
                   j++;
                   d =3D getChar();
@@ -674,7 +674,7 @@ void CssParser::nextToken()
       tval[0] =3D c;
       i =3D 1;
       c =3D getChar();
-      while (isxdigit(c)) {
+      while (isxdigit((uchar_t)c)) {
          if (i < maxStrLen - 1) {
             tval[i] =3D c;
             i++;
diff --git a/src/hsts.c b/src/hsts.c
index f1349c43..dddd86b5 100644
--- a/src/hsts.c
+++ b/src/hsts.c
@@ -223,7 +223,7 @@ void a_Hsts_set(const char *header, const DilloUrl *ur=
l)
       /* Get the value for the attribute and store it */
       if (dStrAsciiCasecmp(attr, "max-age") =3D=3D 0) {
          value =3D Hsts_parse_value(&header);
-         if (isdigit(*value)) {
+         if (isdigit((uchar_t)*value)) {
             errno =3D 0;
             max_age =3D strtol(value, NULL, 10);
             if (errno =3D=3D ERANGE)
diff --git a/src/html.cc b/src/html.cc
index 1a44202d..b418ead2 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -893,7 +893,7 @@ static const char *Html_parse_numeric_charref(DilloHtm=
l *html, char *tok,
    errno =3D 0;
 =

    if (*s =3D=3D 'x' || *s =3D=3D 'X') {
-      if (isxdigit(*++s)) {
+      if (isxdigit((uchar_t)*++s)) {
          /* strtol with base 16 accepts leading "0x" - we don't */
          if (*s =3D=3D '0' && s[1] =3D=3D 'x') {
             s++;
@@ -902,7 +902,7 @@ static const char *Html_parse_numeric_charref(DilloHtm=
l *html, char *tok,
             codepoint =3D strtol(s, &s, 16);
          }
       }
-   } else if (isdigit(*s)) {
+   } else if (isdigit((uchar_t)*s)) {
       codepoint =3D strtol(s, &s, 10);
    }
    if (errno)
@@ -994,7 +994,7 @@ static const char *Html_parse_named_charref(DilloHtml =
*html, char *tok,
    char *s =3D tok;
    const char *ret =3D NULL;
 =

-   while (*++s && (isalnum(*s) || strchr(":_.-", *s))) ;
+   while (*++s && (isalnum((uchar_t)*s) || strchr(":_.-", *s))) ;
    c =3D *s;
    *s =3D '\0';
    if (c !=3D ';') {
@@ -1061,7 +1061,7 @@ static const char *Html_parse_entity(DilloHtml *html=
, const char *token,
 =

    if (*tok =3D=3D '#') {
       ret =3D Html_parse_numeric_charref(html, tok+1, is_attr, entsize);
-   } else if (isalpha(*tok)) {
+   } else if (isalpha((uchar_t)*tok)) {
       ret =3D Html_parse_named_charref(html, tok, is_attr, entsize);
    } else if (prefs.show_extra_warnings &&
        (!(html->DocType =3D=3D DT_HTML && html->DocTypeVersion >=3D 5.0f)=
)) {
@@ -1259,11 +1259,11 @@ static void Html_process_word(DilloHtml *html, con=
st char *word, int size)
       /* all this overhead is to catch white-space entities */
       Pword =3D a_Html_parse_entities(html, word, size);
       for (start =3D i =3D 0; Pword[i]; start =3D i)
-         if (isspace(Pword[i])) {
-            while (Pword[++i] && isspace(Pword[i])) ;
+         if (isspace((uchar_t)Pword[i])) {
+            while (Pword[++i] && isspace((uchar_t)Pword[i])) ;
             Html_process_space(html, Pword + start, i - start);
          } else {
-            while (Pword[++i] && !isspace(Pword[i])) ;
+            while (Pword[++i] && !isspace((uchar_t)Pword[i])) ;
             HT2TB(html)->addText(Pword + start, i - start, html->wordStyl=
e ());
             html->pre_column +=3D i - start;
             html->PreFirstChar =3D false;
@@ -1297,8 +1297,8 @@ static void Html_process_word(DilloHtml *html, const=
 char *word, int size)
       for (start =3D i =3D 0; word2[i]; start =3D i) {
          int len;
 =

-         if (isspace(word2[i])) {
-            while (word2[++i] && isspace(word2[i])) ;
+         if (isspace((uchar_t)word2[i])) {
+            while (word2[++i] && isspace((uchar_t)word2[i])) ;
             Html_process_space(html, word2 + start, i - start);
          } else if (!strncmp(word2+i, utf8_zero_width_space, 3)) {
             i +=3D 3;
@@ -1310,7 +1310,7 @@ static void Html_process_word(DilloHtml *html, const=
 char *word, int size)
          } else {
             do {
                i +=3D len;
-            } while (word2[i] && !isspace(word2[i]) &&
+            } while (word2[i] && !isspace((uchar_t)word2[i]) &&
                      strncmp(word2+i, utf8_zero_width_space, 3) &&
                      (!a_Utf8_ideographic(word2+i, beyond_word2, &len)));
             HT2TB(html)->addText(word2 + start, i - start, html->wordStyl=
e ());
@@ -1334,7 +1334,7 @@ static bool Html_match_tag(const char *tagstr, char =
*tag, int tagsize)
          return false;
    }
    /* The test for '/' is for xml compatibility: "empty/>" will be matche=
d. */
-   if (i < tagsize && (isspace(tag[i]) || tag[i] =3D=3D '>' || tag[i] =3D=
=3D '/'))
+   if (i < tagsize && (isspace((uchar_t)tag[i]) || tag[i] =3D=3D '>' || t=
ag[i] =3D=3D '/'))
       return true;
    return false;
 }
@@ -1451,7 +1451,7 @@ CssLength a_Html_parse_length (DilloHtml *html, cons=
t char *attr)
       l =3D CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
    else {
       /* allow only whitespaces */
-      if (*end && !isspace (*end)) {
+      if (*end && !isspace ((uchar_t)*end)) {
          BUG_MSG("Garbage after length: '%s'.", attr);
          l =3D CSS_CREATE_LENGTH(0.0, CSS_LENGTH_TYPE_AUTO);
       }
@@ -1497,10 +1497,10 @@ static int
       int i;
 =

       for (i =3D 0; val[i]; ++i)
-         if (!d_isascii(val[i]) || !(isalnum(val[i]) || strchr(":_.-", va=
l[i])))
+         if (!d_isascii(val[i]) || !(isalnum((uchar_t)val[i]) || strchr("=
:_.-", val[i])))
             break;
 =

-      if (val[i] || !(d_isascii(val[0]) && isalpha(val[0])))
+      if (val[i] || !(d_isascii(val[0]) && isalpha((uchar_t)val[0])))
          BUG_MSG("%s attribute value \"%s\" is not of the form "
                  "'[A-Za-z][A-Za-z0-9:_.-]*'.", attrname, val);
 =

@@ -1547,8 +1547,8 @@ static void Html_parse_doctype(DilloHtml *html, cons=
t char *tag, int tagsize)
    /* Tag sanitization: Collapse whitespace between tokens
     * and replace '\n' and '\r' with ' ' inside quoted strings. */
    for (i =3D 0, p =3D ntag; *p; ++p) {
-      if (isspace(*p)) {
-         for (ntag[i++] =3D ' '; isspace(p[1]); ++p) ;
+      if (isspace((uchar_t)*p)) {
+         for (ntag[i++] =3D ' '; isspace((uchar_t)p[1]); ++p) ;
       } else if ((quote =3D *p) =3D=3D '"' || *p =3D=3D '\'') {
          for (ntag[i++] =3D *p++; (ntag[i] =3D *p) && ntag[i++] !=3D quot=
e; ++p) {
             if (*p =3D=3D '\n' || *p =3D=3D '\r')
@@ -2390,7 +2390,7 @@ misc::SimpleVector<int> *Html_read_coords(DilloHtml =
*html, const char *str)
          break;
       coords->increase();
       coords->set(coords->size() - 1, coord);
-      while (isspace(*newtail))
+      while (isspace((uchar_t)*newtail))
          newtail++;
       if (!*newtail)
          break;
@@ -4203,7 +4203,7 @@ static const char *Html_get_attr2(DilloHtml *html,
    for (i =3D 1; i < tagsize; ++i) {
       switch (state) {
       case SEEK_ATTR_START:
-         if (isspace(tag[i]))
+         if (isspace((uchar_t)tag[i]))
             state =3D SEEK_TOKEN_START;
          else if (tag[i] =3D=3D '=3D')
             state =3D SEEK_VALUE_START;
@@ -4211,7 +4211,7 @@ static const char *Html_get_attr2(DilloHtml *html,
 =

       case MATCH_ATTR_NAME:
          if (!attrname[attr_pos] &&
-             (tag[i] =3D=3D '=3D' || isspace(tag[i]) || tag[i] =3D=3D '>'=
)) {
+             (tag[i] =3D=3D '=3D' || isspace((uchar_t)tag[i]) || tag[i] =3D=
=3D '>')) {
             Found =3D 1;
             state =3D SEEK_TOKEN_START;
             --i;
@@ -4227,14 +4227,14 @@ static const char *Html_get_attr2(DilloHtml *html,
       case SEEK_TOKEN_START:
          if (tag[i] =3D=3D '=3D') {
             state =3D SEEK_VALUE_START;
-         } else if (!isspace(tag[i])) {
+         } else if (!isspace((uchar_t)tag[i])) {
             attr_pos =3D 0;
             state =3D (Found) ? FINISHED : MATCH_ATTR_NAME;
             --i;
          }
          break;
       case SEEK_VALUE_START:
-         if (!isspace(tag[i])) {
+         if (!isspace((uchar_t)tag[i])) {
             delimiter =3D (tag[i] =3D=3D '"' || tag[i] =3D=3D '\'') ? tag=
[i] : ' ';
             i -=3D (delimiter =3D=3D ' ');
             state =3D (Found) ? GET_VALUE : SKIP_VALUE;
@@ -4242,11 +4242,11 @@ static const char *Html_get_attr2(DilloHtml *html,
          break;
 =

       case SKIP_VALUE:
-         if ((delimiter =3D=3D ' ' && isspace(tag[i])) || tag[i] =3D=3D d=
elimiter)
+         if ((delimiter =3D=3D ' ' && isspace((uchar_t)tag[i])) || tag[i]=
 =3D=3D delimiter)
             state =3D SEEK_TOKEN_START;
          break;
       case GET_VALUE:
-         if ((delimiter =3D=3D ' ' && (isspace(tag[i]) || tag[i] =3D=3D '=
>')) ||
+         if ((delimiter =3D=3D ' ' && (isspace((uchar_t)tag[i]) || tag[i]=
 =3D=3D '>')) ||
              tag[i] =3D=3D delimiter) {
             state =3D FINISHED;
          } else if (tag[i] =3D=3D '&' &&
@@ -4277,10 +4277,10 @@ static const char *Html_get_attr2(DilloHtml *html,
    }
 =

    if (tag_parsing_flags & HTML_LeftTrim)
-      while (isspace(Buf->str[0]))
+      while (isspace((uchar_t)Buf->str[0]))
          dStr_erase(Buf, 0, 1);
    if (tag_parsing_flags & HTML_RightTrim)
-      while (Buf->len && isspace(Buf->str[Buf->len - 1]))
+      while (Buf->len && isspace((uchar_t)Buf->str[Buf->len - 1]))
          dStr_truncate(Buf, Buf->len - 1);
 =

    return (Found) ? Buf->str : NULL;
@@ -4374,14 +4374,14 @@ static int Html_write_raw(DilloHtml *html, char *b=
uf, int bufsize, int Eof)
             break;
       }
 =

-      if (isspace(buf[buf_index])) {
+      if (isspace((uchar_t)buf[buf_index])) {
          /* whitespace: group all available whitespace */
-         while (++buf_index < bufsize && isspace(buf[buf_index])) ;
+         while (++buf_index < bufsize && isspace((uchar_t)buf[buf_index])=
) ;
          Html_process_space(html, buf + token_start, buf_index - token_st=
art);
          token_start =3D buf_index;
 =

       } else if (buf[buf_index] =3D=3D '<' && (ch =3D buf[buf_index + 1])=
 &&
-                 (isalpha(ch) || strchr("/!?", ch)) ) {
+                 (isalpha((uchar_t)ch) || strchr("/!?", ch)) ) {
          /* Tag */
          if (buf_index + 3 < bufsize && !strncmp(buf + buf_index, "<!--",=
 4)) {
             /* Comment: search for close of comment, skipping over
@@ -4447,7 +4447,7 @@ static int Html_write_raw(DilloHtml *html, char *buf=
, int bufsize, int Eof)
          while (++buf_index < bufsize) {
             buf_index +=3D strcspn(buf + buf_index, " <\n\r\t\f\v");
             if (buf[buf_index] =3D=3D '<' && (ch =3D buf[buf_index + 1]) =
&&
-                !isalpha(ch) && !strchr("/!?", ch))
+                !isalpha((uchar_t)ch) && !strchr("/!?", ch))
                continue;
             break;
          }
diff --git a/src/keys.cc b/src/keys.cc
index 69256d6d..ac30b967 100644
--- a/src/keys.cc
+++ b/src/keys.cc
@@ -216,7 +216,7 @@ KeysCommand_t Keys::getKeyCmd()
    KeyBinding_t keyNode;
 =

    keyNode.modifier =3D Fl::event_state() & (FL_SHIFT | FL_CTRL |FL_ALT|F=
L_META);
-   if (iscntrl(Fl::event_text()[0])) {
+   if (iscntrl((uchar_t)Fl::event_text()[0])) {
       keyNode.key =3D Fl::event_key();
    } else {
       const char *beyond =3D Fl::event_text() + Fl::event_length();
@@ -359,7 +359,7 @@ void Keys::parseKey(char *key, char *commandName)
    }
 =

    // Skip space
-   for (  ; isspace(*key); ++key) ;
+   for (  ; isspace((uchar_t)*key); ++key) ;
    // Get modifiers
    while(*key =3D=3D '<' && (p =3D strchr(key, '>'))) {
       ++key;
diff --git a/src/table.cc b/src/table.cc
index 6d144380..544d571f 100644
--- a/src/table.cc
+++ b/src/table.cc
@@ -51,7 +51,7 @@ void Html_tag_open_table(DilloHtml *html, const char *ta=
g, int tagsize)
    CssLength cssLength;
 =

    if ((attrbuf =3D a_Html_get_attr(html, tag, tagsize, "border")))
-      border =3D isdigit(attrbuf[0]) ? strtol (attrbuf, NULL, 10) : 1;
+      border =3D isdigit((uchar_t)attrbuf[0]) ? strtol (attrbuf, NULL, 10=
) : 1;
    if ((attrbuf =3D a_Html_get_attr(html, tag, tagsize, "cellspacing"))) =
{
       cellspacing =3D strtol (attrbuf, NULL, 10);
       if (html->DocType =3D=3D DT_HTML && html->DocTypeVersion >=3D 5.0f)
diff --git a/test/unit/cookies.c b/test/unit/cookies.c
index 40a19418..925bcea9 100644
--- a/test/unit/cookies.c
+++ b/test/unit/cookies.c
@@ -126,7 +126,7 @@ static int Dpi_read_comm_keys(int *port)
       MSG_ERR("[Dpi_read_comm_keys] empty file: %s\n", fname);
    } else {
       *port =3D strtol(rcline, &tail, 10);
-      for (i =3D 0; *tail && isxdigit(tail[i+1]); ++i)
+      for (i =3D 0; *tail && isxdigit((uchar_t)tail[i+1]); ++i)
          SharedKey[i] =3D tail[i+1];
       SharedKey[i] =3D 0;
       ret =3D 1;
-- =

2.52.0


------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Dillo-dev mailing list -- dillo-dev-lx9mn2B4QYRWk0Htik3J/[email protected]
To unsubscribe send an email to dillo-dev-leave-lx9mn2B4QYRWk0Htik3J/[email protected]

------- =_aaaaaaaaaa0--