This has been added to avoid the situation where some host ctype.h functions
authorPauli <paul.dale@oracle.com>
Sun, 20 Aug 2017 21:19:17 +0000 (07:19 +1000)
committerPauli <paul.dale@oracle.com>
Mon, 21 Aug 2017 23:45:25 +0000 (09:45 +1000)
return true for characters > 127.  I.e. they are allowing extended ASCII
characters through which then cause problems.  E.g. marking superscript '2' as
a number then causes the common (ch - '0') conversion to number to fail
miserably.  Likewise letters with diacritical marks can also cause problems.

If a non-ASCII character set is being used (currently only EBCDIC), it is
adjusted for.

The implementation uses a single table with a bit for each of the defined
classes.  These functions accept an int argument and fail for
values out of range or for characters outside of the ASCII set.  They will
work for both signed and unsigned character inputs.

Reviewed-by: Andy Polyakov <appro@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4102)

34 files changed:
crypto/asn1/a_gentm.c
crypto/asn1/a_mbstr.c
crypto/asn1/a_object.c
crypto/asn1/a_print.c
crypto/asn1/a_strnid.c
crypto/asn1/a_time.c
crypto/asn1/a_utctm.c
crypto/asn1/asn_mime.c
crypto/asn1/asn_moid.c
crypto/asn1/asn_mstbl.c
crypto/asn1/f_int.c
crypto/asn1/f_string.c
crypto/bio/b_addr.c
crypto/bio/b_print.c
crypto/bn/bn_print.c
crypto/build.info
crypto/ctype.c [new file with mode: 0644]
crypto/evp/evp_cnf.c
crypto/include/internal/ctype.h [new file with mode: 0644]
crypto/o_str.c
crypto/objects/obj_dat.c
crypto/ocsp/ocsp_ht.c
crypto/pem/pem_lib.c
crypto/pkcs7/pk7_mime.c
crypto/store/loader_file.c
crypto/store/store_register.c
crypto/x509/x509_cmp.c
crypto/x509/x509_vfy.c
crypto/x509/x_name.c
crypto/x509v3/v3_conf.c
crypto/x509v3/v3_utl.c
test/build.info
test/ctype_internal_test.c [new file with mode: 0644]
test/recipes/02-test_internal_ctype.t [new file with mode: 0644]

index 4e2e815..d3878d6 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <stdio.h>
 #include <time.h>
-#include <ctype.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 #include "asn1_locl.h"
index e644fe0..949fe6c 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 
@@ -22,8 +22,6 @@ static int cpy_asc(unsigned long value, void *arg);
 static int cpy_bmp(unsigned long value, void *arg);
 static int cpy_univ(unsigned long value, void *arg);
 static int cpy_utf8(unsigned long value, void *arg);
-static int is_numeric(unsigned long value);
-static int is_printable(unsigned long value);
 
 /*
  * These functions take a string in UTF8, ASCII or multibyte form and a mask
@@ -271,13 +269,15 @@ static int out_utf8(unsigned long value, void *arg)
 
 static int type_str(unsigned long value, void *arg)
 {
-    unsigned long types;
-    types = *((unsigned long *)arg);
-    if ((types & B_ASN1_NUMERICSTRING) && !is_numeric(value))
+    unsigned long types = *((unsigned long *)arg);
+    const int native = value > INT_MAX ? INT_MAX : ossl_fromascii(value);
+
+    if ((types & B_ASN1_NUMERICSTRING) && !(ossl_isdigit(native)
+                                            || native == ' '))
         types &= ~B_ASN1_NUMERICSTRING;
-    if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
+    if ((types & B_ASN1_PRINTABLESTRING) && !ossl_isasn1print(native))
         types &= ~B_ASN1_PRINTABLESTRING;
-    if ((types & B_ASN1_IA5STRING) && (value > 127))
+    if ((types & B_ASN1_IA5STRING) && !ossl_isascii(native))
         types &= ~B_ASN1_IA5STRING;
     if ((types & B_ASN1_T61STRING) && (value > 0xff))
         types &= ~B_ASN1_T61STRING;
@@ -341,55 +341,3 @@ static int cpy_utf8(unsigned long value, void *arg)
     *p += ret;
     return 1;
 }
-
-/* Return 1 if the character is permitted in a PrintableString */
-static int is_printable(unsigned long value)
-{
-    int ch;
-    if (value > 0x7f)
-        return 0;
-    ch = (int)value;
-    /*
-     * Note: we can't use 'isalnum' because certain accented characters may
-     * count as alphanumeric in some environments.
-     */
-#ifndef CHARSET_EBCDIC
-    if ((ch >= 'a') && (ch <= 'z'))
-        return 1;
-    if ((ch >= 'A') && (ch <= 'Z'))
-        return 1;
-    if ((ch >= '0') && (ch <= '9'))
-        return 1;
-    if ((ch == ' ') || strchr("'()+,-./:=?", ch))
-        return 1;
-#else                           /* CHARSET_EBCDIC */
-    if ((ch >= os_toascii['a']) && (ch <= os_toascii['z']))
-        return 1;
-    if ((ch >= os_toascii['A']) && (ch <= os_toascii['Z']))
-        return 1;
-    if ((ch >= os_toascii['0']) && (ch <= os_toascii['9']))
-        return 1;
-    if ((ch == os_toascii[' ']) || strchr("'()+,-./:=?", os_toebcdic[ch]))
-        return 1;
-#endif                          /* CHARSET_EBCDIC */
-    return 0;
-}
-
-/* Return 1 if the character is a digit or space */
-static int is_numeric(unsigned long value)
-{
-    int ch;
-    if (value > 0x7f)
-        return 0;
-    ch = (int)value;
-#ifndef CHARSET_EBCDIC
-    if (!isdigit(ch) && ch != ' ')
-        return 0;
-#else
-    if (ch > os_toascii['9'])
-        return 0;
-    if (ch < os_toascii['0'] && ch != os_toascii[' '])
-        return 0;
-#endif
-    return 1;
-}
index 5ae56a2..566d8b3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -9,7 +9,7 @@
 
 #include <stdio.h>
 #include <limits.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/buffer.h>
 #include <openssl/asn1.h>
@@ -85,7 +85,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
             c = *(p++);
             if ((c == ' ') || (c == '.'))
                 break;
-            if (!isdigit(c)) {
+            if (!ossl_isdigit(c)) {
                 ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
                 goto err;
             }
index 1aafe7c..ed72b51 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 
@@ -25,24 +25,10 @@ int ASN1_PRINTABLE_type(const unsigned char *s, int len)
 
     while ((*s) && (len-- != 0)) {
         c = *(s++);
-#ifndef CHARSET_EBCDIC
-        if (!(((c >= 'a') && (c <= 'z')) ||
-              ((c >= 'A') && (c <= 'Z')) ||
-              ((c >= '0') && (c <= '9')) ||
-              (c == ' ') || (c == '\'') ||
-              (c == '(') || (c == ')') ||
-              (c == '+') || (c == ',') ||
-              (c == '-') || (c == '.') ||
-              (c == '/') || (c == ':') || (c == '=') || (c == '?')))
+        if (!ossl_isasn1print(c))
             ia5 = 1;
-        if (c & 0x80)
+        if (!ossl_isascii(c))
             t61 = 1;
-#else
-        if (!isalnum(c) && (c != ' ') && strchr("'()+,-./:=?", c) == NULL)
-            ia5 = 1;
-        if (os_toascii[c] & 0x80)
-            t61 = 1;
-#endif
     }
     if (t61)
         return (V_ASN1_T61STRING);
index 04c77eb..a7d6b0e 100644 (file)
@@ -8,7 +8,6 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 #include <openssl/objects.h>
index 507292b..cb19e80 100644 (file)
@@ -16,7 +16,7 @@
 
 #include <stdio.h>
 #include <time.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
 #include "asn1_locl.h"
@@ -124,14 +124,14 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
             i++;
             break;
         }
-        if (!isdigit(a[o]))
+        if (!ossl_isdigit(a[o]))
             goto err;
         n = a[o] - '0';
         /* incomplete 2-digital number */
         if (++o == l)
             goto err;
 
-        if (!isdigit(a[o]))
+        if (!ossl_isdigit(a[o]))
             goto err;
         n = (n * 10) + a[o] - '0';
         /* no more bytes to read, but we haven't seen time-zone yet */
@@ -192,7 +192,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
         if (++o == l)
             goto err;
         i = o;
-        while ((o < l) && isdigit(a[o]))
+        while ((o < l) && ossl_isdigit(a[o]))
             o++;
         /* Must have at least one digit after decimal point */
         if (i == o)
@@ -223,11 +223,11 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
         if (o + 4 != l)
             goto err;
         for (i = end; i < end + 2; i++) {
-            if (!isdigit(a[o]))
+            if (!ossl_isdigit(a[o]))
                 goto err;
             n = a[o] - '0';
             o++;
-            if (!isdigit(a[o]))
+            if (!ossl_isdigit(a[o]))
                 goto err;
             n = (n * 10) + a[o] - '0';
             i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
@@ -489,7 +489,7 @@ int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
         if (tm->length > 15 && v[14] == '.') {
             f = &v[14];
             f_len = 1;
-            while (14 + f_len < l && isdigit(f[f_len]))
+            while (14 + f_len < l && ossl_isdigit(f[f_len]))
                 ++f_len;
         }
 
index b88aa42..b224991 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <stdio.h>
 #include <time.h>
-#include <ctype.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 #include "asn1_locl.h"
index d7ec801..01638da 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/rand.h>
 #include <openssl/x509.h>
@@ -634,7 +634,7 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
         return NULL;
     while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
         /* If whitespace at line start then continuation line */
-        if (mhdr && isspace((unsigned char)linebuf[0]))
+        if (mhdr && ossl_isspace(linebuf[0]))
             state = MIME_NAME;
         else
             state = MIME_START;
@@ -758,7 +758,7 @@ static char *strip_start(char *name)
             /* Else null string */
             return NULL;
         }
-        if (!isspace((unsigned char)c))
+        if (!ossl_isspace(c))
             return p;
     }
     return NULL;
@@ -779,7 +779,7 @@ static char *strip_end(char *name)
             *p = 0;
             return name;
         }
-        if (isspace((unsigned char)c))
+        if (ossl_isspace(c))
             *p = 0;
         else
             return name;
@@ -791,29 +791,18 @@ static MIME_HEADER *mime_hdr_new(const char *name, const char *value)
 {
     MIME_HEADER *mhdr = NULL;
     char *tmpname = NULL, *tmpval = NULL, *p;
-    int c;
 
     if (name) {
         if ((tmpname = OPENSSL_strdup(name)) == NULL)
             return NULL;
-        for (p = tmpname; *p; p++) {
-            c = (unsigned char)*p;
-            if (isupper(c)) {
-                c = tolower(c);
-                *p = c;
-            }
-        }
+        for (p = tmpname; *p; p++)
+            *p = ossl_tolower(*p);
     }
     if (value) {
         if ((tmpval = OPENSSL_strdup(value)) == NULL)
             goto err;
-        for (p = tmpval; *p; p++) {
-            c = (unsigned char)*p;
-            if (isupper(c)) {
-                c = tolower(c);
-                *p = c;
-            }
-        }
+        for (p = tmpval; *p; p++)
+            *p = ossl_tolower(*p);
     }
     mhdr = OPENSSL_malloc(sizeof(*mhdr));
     if (mhdr == NULL)
@@ -834,19 +823,14 @@ static MIME_HEADER *mime_hdr_new(const char *name, const char *value)
 static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value)
 {
     char *tmpname = NULL, *tmpval = NULL, *p;
-    int c;
     MIME_PARAM *mparam = NULL;
+
     if (name) {
         tmpname = OPENSSL_strdup(name);
         if (!tmpname)
             goto err;
-        for (p = tmpname; *p; p++) {
-            c = (unsigned char)*p;
-            if (isupper(c)) {
-                c = tolower(c);
-                *p = c;
-            }
-        }
+        for (p = tmpname; *p; p++)
+            *p = ossl_tolower(*p);
     }
     if (value) {
         tmpval = OPENSSL_strdup(value);
index 8176b76..ed8517c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include <openssl/crypto.h>
 #include "internal/cryptlib.h"
 #include <openssl/conf.h>
@@ -72,7 +72,7 @@ static int do_create(const char *value, const char *name)
         ostr = p + 1;
         if (!*ostr)
             return 0;
-        while (isspace((unsigned char)*ostr))
+        while (ossl_isspace(*ostr))
             ostr++;
     }
 
@@ -83,10 +83,10 @@ static int do_create(const char *value, const char *name)
 
     if (p) {
         ln = value;
-        while (isspace((unsigned char)*ln))
+        while (ossl_isspace(*ln))
             ln++;
         p--;
-        while (isspace((unsigned char)*p)) {
+        while (ossl_isspace(*p)) {
             if (p == ln)
                 return 0;
             p--;
index 8260939..ddcbcd0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,6 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
 #include <openssl/crypto.h>
 #include "internal/cryptlib.h"
 #include <openssl/conf.h>
index ec556c9..ee035b7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/buffer.h>
 #include <openssl/asn1.h>
@@ -76,18 +76,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
         again = (buf[i - 1] == '\\');
 
         for (j = 0; j < i; j++) {
-#ifndef CHARSET_EBCDIC
-            if (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
-                  ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
-                  ((buf[j] >= 'A') && (buf[j] <= 'F'))))
-#else
-            /*
-             * This #ifdef is not strictly necessary, since the characters
-             * A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but
-             * not the whole alphabet). Nevertheless, isxdigit() is faster.
-             */
-            if (!isxdigit(buf[j]))
-#endif
+            if (!ossl_isxdigit(buf[j]))
             {
                 i = j;
                 break;
index b9258bb..cfb895f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/buffer.h>
 #include <openssl/asn1.h>
@@ -47,7 +47,7 @@ int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type)
 
 int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
 {
-    int i, j, k, m, n, again, bufsize, spec_char;
+    int i, j, k, m, n, again, bufsize;
     unsigned char *s = NULL, *sp;
     unsigned char *bufp;
     int num = 0, slen = 0, first = 1;
@@ -74,19 +74,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
         again = (buf[i - 1] == '\\');
 
         for (j = i - 1; j > 0; j--) {
-#ifndef CHARSET_EBCDIC
-            spec_char = (!(((buf[j] >= '0') && (buf[j] <= '9')) ||
-                  ((buf[j] >= 'a') && (buf[j] <= 'f')) ||
-                  ((buf[j] >= 'A') && (buf[j] <= 'F'))));
-#else
-            /*
-             * This #ifdef is not strictly necessary, since the characters
-             * A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but
-             * not the whole alphabet). Nevertheless, isxdigit() is faster.
-             */
-            spec_char = (!isxdigit(buf[j]));
-#endif
-            if (spec_char) {
+            if (!ossl_isxdigit(buf[j])) {
                 i = j;
                 break;
             }
index d0b2428..6d85492 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -17,7 +17,6 @@
 #include <openssl/err.h>
 #include <openssl/buffer.h>
 #include <internal/thread_once.h>
-#include <ctype.h>
 
 CRYPTO_RWLOCK *bio_lookup_lock;
 static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT;
index ebb6845..eeee52e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -9,7 +9,7 @@
 
 #include <stdio.h>
 #include <string.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/numbers.h"
 #include "internal/cryptlib.h"
 #include <openssl/bio.h>
@@ -143,7 +143,7 @@ _dopr(char **sbuffer,
             }
             break;
         case DP_S_MIN:
-            if (isdigit((unsigned char)ch)) {
+            if (ossl_isdigit(ch)) {
                 min = 10 * min + char_to_int(ch);
                 ch = *format++;
             } else if (ch == '*') {
@@ -161,7 +161,7 @@ _dopr(char **sbuffer,
                 state = DP_S_MOD;
             break;
         case DP_S_MAX:
-            if (isdigit((unsigned char)ch)) {
+            if (ossl_isdigit(ch)) {
                 if (max < 0)
                     max = 0;
                 max = 10 * max + char_to_int(ch);
index 9f84997..bfbaf5c 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include <limits.h>
 #include "internal/cryptlib.h"
 #include <openssl/buffer.h>
@@ -138,7 +138,7 @@ int BN_hex2bn(BIGNUM **bn, const char *a)
         a++;
     }
 
-    for (i = 0; i <= (INT_MAX/4) && isxdigit((unsigned char)a[i]); i++)
+    for (i = 0; i <= (INT_MAX/4) && ossl_isxdigit(a[i]); i++)
         continue;
 
     if (i == 0 || i > INT_MAX/4)
@@ -210,7 +210,7 @@ int BN_dec2bn(BIGNUM **bn, const char *a)
         a++;
     }
 
-    for (i = 0; i <= (INT_MAX/4) && isdigit((unsigned char)a[i]); i++)
+    for (i = 0; i <= (INT_MAX/4) && ossl_isdigit(a[i]); i++)
         continue;
 
     if (i == 0 || i > INT_MAX/4)
index 916d24f..983708a 100644 (file)
@@ -2,7 +2,7 @@
 LIBS=../libcrypto
 SOURCE[../libcrypto]=\
         cryptlib.c mem.c mem_dbg.c cversion.c ex_data.c cpt_err.c \
-        ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c \
+        ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c ctype.c \
         threads_pthread.c threads_win.c threads_none.c \
         o_init.c o_fips.c mem_sec.c init.c {- $target{cpuid_asm_src} -} \
         {- $target{uplink_aux_src} -}
diff --git a/crypto/ctype.c b/crypto/ctype.c
new file mode 100644 (file)
index 0000000..89ed5bf
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include "internal/ctype.h"
+#include "openssl/ebcdic.h"
+
+/*
+ * Define the character classes for each character in the seven bit ASCII
+ * character set.  This is independent of the host's character set, characters
+ * are converted to ASCII before being used as an index in to this table.
+ * Characters outside of the seven bit ASCII range are detected before indexing.
+ */
+static const unsigned short ctype_char_map[128] = {
+   /* 00 nul */ CTYPE_MASK_cntrl,
+   /* 01 soh */ CTYPE_MASK_cntrl,
+   /* 02 stx */ CTYPE_MASK_cntrl,
+   /* 03 etx */ CTYPE_MASK_cntrl,
+   /* 04 eot */ CTYPE_MASK_cntrl,
+   /* 05 enq */ CTYPE_MASK_cntrl,
+   /* 06 ack */ CTYPE_MASK_cntrl,
+   /* 07 \a  */ CTYPE_MASK_cntrl,
+   /* 08 \b  */ CTYPE_MASK_cntrl,
+   /* 09 \t  */ CTYPE_MASK_blank | CTYPE_MASK_cntrl | CTYPE_MASK_space,
+   /* 0A \n  */ CTYPE_MASK_cntrl | CTYPE_MASK_space,
+   /* 0B \v  */ CTYPE_MASK_cntrl | CTYPE_MASK_space,
+   /* 0C \f  */ CTYPE_MASK_cntrl | CTYPE_MASK_space,
+   /* 0D \r  */ CTYPE_MASK_cntrl | CTYPE_MASK_space,
+   /* 0E so  */ CTYPE_MASK_cntrl,
+   /* 0F si  */ CTYPE_MASK_cntrl,
+   /* 10 dle */ CTYPE_MASK_cntrl,
+   /* 11 dc1 */ CTYPE_MASK_cntrl,
+   /* 12 dc2 */ CTYPE_MASK_cntrl,
+   /* 13 dc3 */ CTYPE_MASK_cntrl,
+   /* 14 dc4 */ CTYPE_MASK_cntrl,
+   /* 15 nak */ CTYPE_MASK_cntrl,
+   /* 16 syn */ CTYPE_MASK_cntrl,
+   /* 17 etb */ CTYPE_MASK_cntrl,
+   /* 18 can */ CTYPE_MASK_cntrl,
+   /* 19 em  */ CTYPE_MASK_cntrl,
+   /* 1A sub */ CTYPE_MASK_cntrl,
+   /* 1B esc */ CTYPE_MASK_cntrl,
+   /* 1C fs  */ CTYPE_MASK_cntrl,
+   /* 1D gs  */ CTYPE_MASK_cntrl,
+   /* 1E rs  */ CTYPE_MASK_cntrl,
+   /* 1F us  */ CTYPE_MASK_cntrl,
+   /* 20     */ CTYPE_MASK_blank | CTYPE_MASK_print | CTYPE_MASK_space
+                | CTYPE_MASK_asn1print,
+   /* 21  !  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 22  "  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 23  #  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 24  $  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 25  %  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 26  &  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 27  '  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_asn1print,
+   /* 28  (  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_asn1print,
+   /* 29  )  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_asn1print,
+   /* 2A  *  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 2B  +  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 2C  ,  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_asn1print,
+   /* 2D  -  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_asn1print,
+   /* 2E  .  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_asn1print,
+   /* 2F  /  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 30  0  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 31  1  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 32  2  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 33  3  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 34  4  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 35  5  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 36  6  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 37  7  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 38  8  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 39  9  */ CTYPE_MASK_digit | CTYPE_MASK_graph | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 3A  :  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_asn1print,
+   /* 3B  ;  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 3C  <  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 3D  =  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 3E  >  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 3F  ?  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct
+                | CTYPE_MASK_asn1print,
+   /* 40  @  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 41  A  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 42  B  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 43  C  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 44  D  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 45  E  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 46  F  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 47  G  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 48  H  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 49  I  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 4A  J  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 4B  K  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 4C  L  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 4D  M  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 4E  N  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 4F  O  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 50  P  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 51  Q  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 52  R  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 53  S  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 54  T  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 55  U  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 56  V  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 57  W  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 58  X  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 59  Y  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 5A  Z  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_upper
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 5B  [  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 5C  \  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 5D  ]  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 5E  ^  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 5F  _  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 60  `  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 61  a  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 62  b  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 63  c  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 64  d  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 65  e  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 66  f  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_xdigit | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 67  g  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 68  h  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 69  i  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 6A  j  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 6B  k  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 6C  l  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 6D  m  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 6E  n  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 6F  o  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 70  p  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 71  q  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 72  r  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 73  s  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 74  t  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 75  u  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 76  v  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 77  w  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 78  x  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 79  y  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 7A  z  */ CTYPE_MASK_graph | CTYPE_MASK_lower | CTYPE_MASK_print
+                | CTYPE_MASK_base64 | CTYPE_MASK_asn1print,
+   /* 7B  {  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 7C  |  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 7D  }  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 7E  ~  */ CTYPE_MASK_graph | CTYPE_MASK_print | CTYPE_MASK_punct,
+   /* 7F del */ CTYPE_MASK_cntrl
+};
+
+#ifdef CHARSET_EBCDIC
+int ossl_toascii(int c)
+{
+    if (c < -128 || c > 256)
+        return c;
+    /*
+     * Adjust negatively signed characters.
+     * This is not required for ASCII because any character that sign extends
+     * is not seven bit and all of the checks are on the seven bit characters.
+     * I.e. any check must fail on sign extension.
+     */
+    if (c < 0)
+        c += 256;
+    return os_toascii[c];
+}
+
+int ossl_fromascii(int c)
+{
+    if (c < -128 || c > 256)
+        return c;
+    if (c < 0)
+        c += 256;
+    return os_toebcdic[c];
+}
+#endif
+
+int ossl_ctype_check(int c, unsigned int mask)
+{
+    const int max = sizeof(ctype_char_map) / sizeof(*ctype_char_map);
+
+    c = ossl_toascii(c);
+    return c >= 0 && c < max && (ctype_char_map[c] & mask) != 0;
+}
+
+#if defined(CHARSET_EBCDIC) && !defined(CHARSET_EBCDIC_TEST)
+static const int case_change = 0x40;
+#else
+static const int case_change = 0x20;
+#endif
+
+int ossl_tolower(int c)
+{
+    return ossl_isupper(c) ? c ^ case_change : c;
+}
+
+int ossl_toupper(int c)
+{
+    return ossl_islower(c) ? c ^ case_change : c;
+}
index d0d61b2..8df2c06 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,6 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
 #include <openssl/crypto.h>
 #include "internal/cryptlib.h"
 #include <openssl/conf.h>
diff --git a/crypto/include/internal/ctype.h b/crypto/include/internal/ctype.h
new file mode 100644 (file)
index 0000000..a35b12b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This version of ctype.h provides a standardised and platform
+ * independent implementation that supports seven bit ASCII characters.
+ * The specific intent is to not pass extended ASCII characters (> 127)
+ * even if the host operating system would.
+ *
+ * There is EBCDIC support included for machines which use this.  However,
+ * there are a number of concerns about how well EBCDIC is supported
+ * throughout the rest of the source code.  Refer to issue #4154 for
+ * details.
+ */
+#ifndef INTERNAL_CTYPE_H
+# define INTERNAL_CTYPE_H
+
+# define CTYPE_MASK_lower       0x1
+# define CTYPE_MASK_upper       0x2
+# define CTYPE_MASK_digit       0x4
+# define CTYPE_MASK_space       0x8
+# define CTYPE_MASK_xdigit      0x10
+# define CTYPE_MASK_blank       0x20
+# define CTYPE_MASK_cntrl       0x40
+# define CTYPE_MASK_graph       0x80
+# define CTYPE_MASK_print       0x100
+# define CTYPE_MASK_punct       0x200
+# define CTYPE_MASK_base64      0x400
+# define CTYPE_MASK_asn1print   0x800
+
+# define CTYPE_MASK_alpha   (CTYPE_MASK_lower | CTYPE_MASK_upper)
+# define CTYPE_MASK_alnum   (CTYPE_MASK_alpha | CTYPE_MASK_digit)
+
+/*
+ * The ascii mask assumes that any other classification implies that
+ * the character is ASCII and that there are no ASCII characters
+ * that aren't in any of the classifications.
+ *
+ * This assumption holds at the moment, but it might not in the future.
+ */
+# define CTYPE_MASK_ascii   (~0)
+
+# ifdef CHARSET_EBCDIC
+int ossl_toascii(int c);
+int ossl_fromascii(int c);
+# else
+#  define ossl_toascii(c)       (c)
+#  define ossl_fromascii(c)     (c)
+# endif
+int ossl_ctype_check(int c, unsigned int mask);
+int ossl_tolower(int c);
+int ossl_toupper(int c);
+
+# define ossl_isalnum(c)        (ossl_ctype_check((c), CTYPE_MASK_alnum))
+# define ossl_isalpha(c)        (ossl_ctype_check((c), CTYPE_MASK_alpha))
+# ifdef CHARSET_EBCDIC
+# define ossl_isascii(c)        (ossl_ctype_check((c), CTYPE_MASK_ascii))
+# else
+# define ossl_isascii(c)        (((c) & ~127) == 0)
+# endif
+# define ossl_isblank(c)        (ossl_ctype_check((c), CTYPE_MASK_blank))
+# define ossl_iscntrl(c)        (ossl_ctype_check((c), CTYPE_MASK_cntrl))
+# define ossl_isdigit(c)        (ossl_ctype_check((c), CTYPE_MASK_digit))
+# define ossl_isgraph(c)        (ossl_ctype_check((c), CTYPE_MASK_graph))
+# define ossl_islower(c)        (ossl_ctype_check((c), CTYPE_MASK_lower))
+# define ossl_isprint(c)        (ossl_ctype_check((c), CTYPE_MASK_print))
+# define ossl_ispunct(c)        (ossl_ctype_check((c), CTYPE_MASK_punct))
+# define ossl_isspace(c)        (ossl_ctype_check((c), CTYPE_MASK_space))
+# define ossl_isupper(c)        (ossl_ctype_check((c), CTYPE_MASK_upper))
+# define ossl_isxdigit(c)       (ossl_ctype_check((c), CTYPE_MASK_xdigit))
+# define ossl_isbase64(c)       (ossl_ctype_check((c), CTYPE_MASK_base64))
+# define ossl_isasn1print(c)    (ossl_ctype_check((c), CTYPE_MASK_asn1print))
+
+#endif
index 528655a..c762b70 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2003-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,7 +7,6 @@
  * https://www.openssl.org/source/license.html
  */
 
-#include <ctype.h>
 #include <limits.h>
 #include <e_os.h>
 #include <openssl/crypto.h>
index 4de346b..3f65d37 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include <limits.h>
 #include "internal/cryptlib.h"
 #include <openssl/lhash.h>
@@ -644,24 +644,24 @@ int OBJ_create_objects(BIO *in)
         if (i <= 0)
             return num;
         buf[i - 1] = '\0';
-        if (!isalnum((unsigned char)buf[0]))
+        if (!ossl_isalnum(buf[0]))
             return num;
         o = s = buf;
-        while (isdigit((unsigned char)*s) || (*s == '.'))
+        while (ossl_isdigit(*s) || *s == '.')
             s++;
         if (*s != '\0') {
             *(s++) = '\0';
-            while (isspace((unsigned char)*s))
+            while (ossl_isspace(*s))
                 s++;
             if (*s == '\0')
                 s = NULL;
             else {
                 l = s;
-                while ((*l != '\0') && !isspace((unsigned char)*l))
+                while (*l != '\0' && !ossl_isspace(*l))
                     l++;
                 if (*l != '\0') {
                     *(l++) = '\0';
-                    while (isspace((unsigned char)*l))
+                    while (ossl_isspace(*l))
                         l++;
                     if (*l == '\0')
                         l = NULL;
index d8796ca..ef84a2d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -9,7 +9,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include <string.h>
 #include "e_os.h"
 #include <openssl/asn1.h>
@@ -209,7 +209,7 @@ static int parse_http_line1(char *line)
     char *p, *q, *r;
     /* Skip to first white space (passed protocol info) */
 
-    for (p = line; *p && !isspace((unsigned char)*p); p++)
+    for (p = line; *p && !ossl_isspace(*p); p++)
         continue;
     if (!*p) {
         OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
@@ -217,7 +217,7 @@ static int parse_http_line1(char *line)
     }
 
     /* Skip past white space to start of response code */
-    while (*p && isspace((unsigned char)*p))
+    while (*p && ossl_isspace(*p))
         p++;
 
     if (!*p) {
@@ -226,7 +226,7 @@ static int parse_http_line1(char *line)
     }
 
     /* Find end of response code: first whitespace after start of code */
-    for (q = p; *q && !isspace((unsigned char)*q); q++)
+    for (q = p; *q && !ossl_isspace(*q); q++)
         continue;
 
     if (!*q) {
@@ -244,7 +244,7 @@ static int parse_http_line1(char *line)
         return 0;
 
     /* Skip over any leading white space in message */
-    while (*q && isspace((unsigned char)*q))
+    while (*q && ossl_isspace(*q))
         q++;
 
     if (*q) {
@@ -253,7 +253,7 @@ static int parse_http_line1(char *line)
          */
 
         /* We know q has a non white space character so this is OK */
-        for (r = q + strlen(q) - 1; isspace((unsigned char)*r); r--)
+        for (r = q + strlen(q) - 1; ossl_isspace(*r); r--)
             *r = 0;
     }
     if (retcode != 200) {
index 309545b..97b8a0d 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include <string.h>
 #include "internal/cryptlib.h"
 #include <openssl/buffer.h>
@@ -683,9 +683,6 @@ int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
 #endif
 
 /* Some helpers for PEM_read_bio_ex(). */
-
-#define isb64(c) (isalnum(c) || (c) == '+' || (c) == '/' || (c) == '=')
-
 static int sanitize_line(char *linebuf, int len, unsigned int flags)
 {
     int i;
@@ -698,7 +695,8 @@ static int sanitize_line(char *linebuf, int len, unsigned int flags)
         len++;
     } else if (flags & PEM_FLAG_ONLY_B64) {
         for (i = 0; i < len; ++i) {
-            if (!isb64(linebuf[i]) || linebuf[i] == '\n' || linebuf[i] == '\r')
+            if (!ossl_isbase64(linebuf[i]) || linebuf[i] == '\n'
+                || linebuf[i] == '\r')
                 break;
         }
         len = i;
@@ -708,7 +706,7 @@ static int sanitize_line(char *linebuf, int len, unsigned int flags)
         for (i = 0; i < len; ++i) {
             if (linebuf[i] == '\n' || linebuf[i] == '\r')
                 break;
-            if (iscntrl(linebuf[i]))
+            if (ossl_iscntrl(linebuf[i]))
                 linebuf[i] = ' ';
         }
         len = i;
index 97474cf..19e6868 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,6 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
 #include "internal/cryptlib.h"
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
index 99c9350..f6cb928 100644 (file)
@@ -23,6 +23,7 @@
 #include <openssl/ui.h>
 #include <openssl/x509.h>        /* For the PKCS8 stuff o.O */
 #include "internal/asn1_int.h"
+#include "internal/ctype.h"
 #include "internal/o_dir.h"
 #include "internal/cryptlib.h"
 #include "internal/store_int.h"
@@ -783,7 +784,7 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
 #ifdef _WIN32
         /* Windows file: URIs with a drive letter start with a / */
         if (p[0] == '/' && p[2] == ':' && p[3] == '/') {
-            char c = tolower(p[1]);
+            char c = ossl_tolower(p[1]);
 
             if (c >= 'a' && c <= 'z') {
                 p++;
index 6af7144..85c38b8 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 #include <string.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include <assert.h>
 
 #include <openssl/err.h>
@@ -140,10 +140,10 @@ int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader)
      *
      * scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
      */
-    if (isalpha(*scheme))
+    if (ossl_isalpha(*scheme))
         while (*scheme != '\0'
-               && (isalpha(*scheme)
-                   || isdigit(*scheme)
+               && (ossl_isalpha(*scheme)
+                   || ossl_isdigit(*scheme)
                    || strchr("+-.", *scheme) != NULL))
             scheme++;
     if (*scheme != '\0') {
index 0105635..a5903fd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,6 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 #include <openssl/objects.h>
index af96418..58f88ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,12 +7,12 @@
  * https://www.openssl.org/source/license.html
  */
 
-#include <ctype.h>
 #include <stdio.h>
 #include <time.h>
 #include <errno.h>
 #include <limits.h>
 
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/crypto.h>
 #include <openssl/lhash.h>
@@ -1790,7 +1790,7 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
      * Digit and date ranges will be verified in the conversion methods.
      */
     for (i = 0; i < ctm->length - 1; i++) {
-        if (!isdigit(ctm->data[i]))
+        if (!ossl_isdigit(ctm->data[i]))
             return 0;
     }
     if (ctm->data[ctm->length - 1] != 'Z')
index 97d735f..665a520 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
@@ -398,11 +398,12 @@ static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in)
     /*
      * Convert string in place to canonical form. Ultimately we may need to
      * handle a wider range of characters but for now ignore anything with
-     * MSB set and rely on the isspace() and tolower() functions.
+     * MSB set and rely on the ossl_isspace() to fail on bad characters without
+     * needing isascii or range checks as well.
      */
 
     /* Ignore leading spaces */
-    while ((len > 0) && !(*from & 0x80) && isspace(*from)) {
+    while (len > 0 && ossl_isspace(*from)) {
         from++;
         len--;
     }
@@ -410,7 +411,7 @@ static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in)
     to = from + len;
 
     /* Ignore trailing spaces */
-    while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) {
+    while (len > 0 && ossl_isspace(to[-1])) {
         to--;
         len--;
     }
@@ -419,13 +420,13 @@ static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in)
 
     i = 0;
     while (i < len) {
-        /* If MSB set just copy across */
-        if (*from & 0x80) {
+        /* If not ASCII set just copy across */
+        if (!ossl_isascii(*from)) {
             *to++ = *from++;
             i++;
         }
         /* Collapse multiple spaces */
-        else if (isspace(*from)) {
+        else if (ossl_isspace(*from)) {
             /* Copy one space across */
             *to++ = ' ';
             /*
@@ -437,9 +438,9 @@ static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in)
                 from++;
                 i++;
             }
-            while (!(*from & 0x80) && isspace(*from));
+            while (ossl_isspace(*from));
         } else {
-            *to++ = tolower(*from);
+            *to++ = ossl_tolower(*from);
             from++;
             i++;
         }
@@ -505,19 +506,10 @@ int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
 
     c = s;
     for (;;) {
-#ifndef CHARSET_EBCDIC
         if (((*s == '/') &&
-             ((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') ||
-                                                 ((s[2] >= 'A')
-                                                  && (s[2] <= 'Z')
-                                                  && (s[3] == '='))
+             (ossl_isupper(s[1]) && ((s[2] == '=') ||
+                                (ossl_isupper(s[2]) && (s[3] == '='))
               ))) || (*s == '\0'))
-#else
-        if (((*s == '/') &&
-             (isupper(s[1]) && ((s[2] == '=') ||
-                                (isupper(s[2]) && (s[3] == '='))
-              ))) || (*s == '\0'))
-#endif
         {
             i = s - c;
             if (BIO_write(bp, c, i) != i)
index f625ff5..711ff02 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -10,7 +10,7 @@
 /* extension creation utilities */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/conf.h>
 #include <openssl/x509.h>
@@ -192,7 +192,7 @@ static int v3_check_critical(const char **value)
     if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
         return 0;
     p += 9;
-    while (isspace((unsigned char)*p))
+    while (ossl_isspace(*p))
         p++;
     *value = p;
     return 1;
@@ -212,7 +212,7 @@ static int v3_check_generic(const char **value)
     } else
         return 0;
 
-    while (isspace((unsigned char)*p))
+    while (ossl_isspace(*p))
         p++;
     *value = p;
     return gen_type;
index ac52170..a10722c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -10,7 +10,7 @@
 /* X509 v3 extension utilities */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/conf.h>
 #include <openssl/x509v3.h>
@@ -334,12 +334,12 @@ static char *strip_spaces(char *name)
     char *p, *q;
     /* Skip over leading spaces */
     p = name;
-    while (*p && isspace((unsigned char)*p))
+    while (*p && ossl_isspace(*p))
         p++;
     if (!*p)
         return NULL;
     q = p + strlen(p) - 1;
-    while ((q != p) && isspace((unsigned char)*q))
+    while ((q != p) && ossl_isspace(*q))
         q--;
     if (p != q)
         q[1] = 0;
index 6abd635..f1f26af 100644 (file)
@@ -385,7 +385,7 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
   # names with the DLL import libraries.
   IF[{- $disabled{shared} || $target{build_scheme}->[1] ne 'windows' -}]
     PROGRAMS_NO_INST=asn1_internal_test modes_internal_test x509_internal_test \
-                     tls13encryptiontest wpackettest
+                     tls13encryptiontest wpackettest ctype_internal_test
     IF[{- !$disabled{poly1305} -}]
       PROGRAMS_NO_INST=poly1305_internal_test
     ENDIF
@@ -424,6 +424,10 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=MAIN
     INCLUDE[wpackettest]=../include
     DEPEND[wpackettest]=../libcrypto ../libssl.a libtestutil.a
 
+    SOURCE[ctype_internal_test]=ctype_internal_test.c
+    INCLUDE[ctype_internal_test]=.. ../crypto/include ../include
+    DEPEND[ctype_internal_test]=../libcrypto.a libtestutil.a
+
     SOURCE[siphash_internal_test]=siphash_internal_test.c
     INCLUDE[siphash_internal_test]=.. ../include ../crypto/include
     DEPEND[siphash_internal_test]=../libcrypto.a libtestutil.a
diff --git a/test/ctype_internal_test.c b/test/ctype_internal_test.c
new file mode 100644 (file)
index 0000000..0a30c3d
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "testutil.h"
+#include "internal/ctype.h"
+#include "../e_os.h"
+#include <ctype.h>
+#include <stdio.h>
+
+static int test_ctype_chars(int n)
+{
+    return TEST_int_eq(isalnum(n) != 0, ossl_isalnum(n) != 0)
+           && TEST_int_eq(isalpha(n) != 0, ossl_isalpha(n) != 0)
+           && TEST_int_eq(isascii(n) != 0, ossl_isascii(n) != 0)
+           && TEST_int_eq(isblank(n) != 0, ossl_isblank(n) != 0)
+           && TEST_int_eq(iscntrl(n) != 0, ossl_iscntrl(n) != 0)
+           && TEST_int_eq(isdigit(n) != 0, ossl_isdigit(n) != 0)
+           && TEST_int_eq(isgraph(n) != 0, ossl_isgraph(n) != 0)
+           && TEST_int_eq(islower(n) != 0, ossl_islower(n) != 0)
+           && TEST_int_eq(isprint(n) != 0, ossl_isprint(n) != 0)
+           && TEST_int_eq(ispunct(n) != 0, ossl_ispunct(n) != 0)
+           && TEST_int_eq(isspace(n) != 0, ossl_isspace(n) != 0)
+           && TEST_int_eq(isupper(n) != 0, ossl_isupper(n) != 0)
+           && TEST_int_eq(isxdigit(n) != 0, ossl_isxdigit(n) != 0);
+}
+
+static int test_ctype_negative(int n)
+{
+    return test_ctype_chars(-n);
+}
+
+static struct {
+    int u;
+    int l;
+} case_change[] = {
+    { 'A', 'a' },
+    { 'X', 'x' },
+    { 'Z', 'z' },
+    { '0', '0' },
+    { '%', '%' },
+    { '~', '~' },
+    {   0,   0 },
+    { EOF, EOF },
+    { 333, 333 },
+    { -333, -333 },
+    { -128, -128 }
+};
+
+static int test_ctype_toupper(int n)
+{
+    return TEST_int_eq(ossl_toupper(case_change[n].l), case_change[n].u)
+           && TEST_int_eq(ossl_toupper(case_change[n].u), case_change[n].u);
+}
+
+static int test_ctype_tolower(int n)
+{
+    return TEST_int_eq(ossl_tolower(case_change[n].u), case_change[n].l)
+           && TEST_int_eq(ossl_tolower(case_change[n].l), case_change[n].l);
+}
+
+int setup_tests(void)
+{
+    ADD_ALL_TESTS(test_ctype_chars, 256);
+    ADD_ALL_TESTS(test_ctype_negative, 128);
+    ADD_ALL_TESTS(test_ctype_toupper, OSSL_NELEM(case_change));
+    ADD_ALL_TESTS(test_ctype_tolower, OSSL_NELEM(case_change));
+    return 1;
+}
diff --git a/test/recipes/02-test_internal_ctype.t b/test/recipes/02-test_internal_ctype.t
new file mode 100644 (file)
index 0000000..5bf81bd
--- /dev/null
@@ -0,0 +1,20 @@
+#! /usr/bin/env perl
+# Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright (c) 2017, Oracle and/or its affiliates.  All rights reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+use OpenSSL::Test;              # get 'plan'
+use OpenSSL::Test::Simple;
+use OpenSSL::Test::Utils;
+
+setup("test_internal_ctype");
+
+plan skip_all => "This test is unsupported in a shared library build on Windows"
+    if $^O eq 'MSWin32' && !disabled("shared");
+
+simple_test("test_internal_ctype", "ctype_internal_test");