]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
tolower: refine the tolower code to avoid a memory access
authorPauli <pauli@openssl.org>
Thu, 19 May 2022 02:23:55 +0000 (12:23 +1000)
committerPauli <pauli@openssl.org>
Sun, 22 May 2022 23:51:28 +0000 (09:51 +1000)
This improves the performance of this function and the ones that rely on it
(ossl_lh_strcasehash primarily).

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/18344)

crypto/ctype.c
include/crypto/ctype.h

index 2165213889f4ed34b44efbe23e23cd4b46261b25..de2e836ff7837d32f65e0ac4d4cb06566df7c295 100644 (file)
@@ -257,6 +257,36 @@ int ossl_ctype_check(int c, unsigned int mask)
     return a >= 0 && a < max && (ctype_char_map[a] & mask) != 0;
 }
 
+/*
+ * Implement some of the simplier functions directly to avoid the overhead of
+ * accessing memory via ctype_char_map[].
+ */
+
+#define ASCII_IS_DIGIT(c)   (c >= 0x30 && c <= 0x39)
+#define ASCII_IS_UPPER(c)   (c >= 0x41 && c <= 0x5A)
+#define ASCII_IS_LOWER(c)   (c >= 0x61 && c <= 0x7A)
+
+int ossl_isdigit(int c)
+{
+    int a = ossl_toascii(c);
+
+    return ASCII_IS_DIGIT(a);
+}
+
+int ossl_isupper(int c)
+{
+    int a = ossl_toascii(c);
+
+    return ASCII_IS_UPPER(a);
+}
+
+int ossl_islower(int c)
+{
+    int a = ossl_toascii(c);
+
+    return ASCII_IS_LOWER(a);
+}
+
 #if defined(CHARSET_EBCDIC) && !defined(CHARSET_EBCDIC_TEST)
 static const int case_change = 0x40;
 #else
@@ -265,16 +295,19 @@ static const int case_change = 0x20;
 
 int ossl_tolower(int c)
 {
-    return ossl_isupper(c) ? c ^ case_change : c;
+    int a = ossl_toascii(c);
+
+    return ASCII_IS_UPPER(a) ? c ^ case_change : c;
 }
 
 int ossl_toupper(int c)
 {
-    return ossl_islower(c) ? c ^ case_change : c;
+    int a = ossl_toascii(c);
+
+    return ASCII_IS_LOWER(a) ? c ^ case_change : c;
 }
 
-int ossl_ascii_isdigit(const char inchar) {
-    if (inchar > 0x2F && inchar < 0x3A)
-        return 1;
-    return 0;
+int ossl_ascii_isdigit(int c)
+{
+    return ASCII_IS_DIGIT(c);
 }
index 6deee3b947df30e3fddbf51cd8f07a946ff8b703..22f6922183b582d7fd2bac7d9549a4f06c8e669b 100644 (file)
@@ -22,6 +22,8 @@
 # define OSSL_CRYPTO_CTYPE_H
 # pragma once
 
+# include <openssl/e_os2.h>
+
 # define CTYPE_MASK_lower       0x1
 # define CTYPE_MASK_upper       0x2
 # define CTYPE_MASK_digit       0x4
@@ -55,10 +57,15 @@ int ossl_fromascii(int 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);
 
-int ossl_ascii_isdigit(const char inchar);
+int ossl_isdigit(int c);
+int ossl_islower(int c);
+int ossl_isupper(int c);
+
+int ossl_ascii_isdigit(int c);
 
 # define ossl_isalnum(c)        (ossl_ctype_check((c), CTYPE_MASK_alnum))
 # define ossl_isalpha(c)        (ossl_ctype_check((c), CTYPE_MASK_alpha))
@@ -69,13 +76,10 @@ int ossl_ascii_isdigit(const char inchar);
 # 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))