From: Pauli Date: Thu, 19 May 2022 02:23:55 +0000 (+1000) Subject: tolower: refine the tolower code to avoid a memory access X-Git-Tag: openssl-3.2.0-alpha1~2638 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=286053fc8f78e34828a576830ef879c021640aee;p=thirdparty%2Fopenssl.git tolower: refine the tolower code to avoid a memory access This improves the performance of this function and the ones that rely on it (ossl_lh_strcasehash primarily). Reviewed-by: Tomas Mraz Reviewed-by: Tim Hudson Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/18344) --- diff --git a/crypto/ctype.c b/crypto/ctype.c index 2165213889f..de2e836ff78 100644 --- a/crypto/ctype.c +++ b/crypto/ctype.c @@ -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); } diff --git a/include/crypto/ctype.h b/include/crypto/ctype.h index 6deee3b947d..22f6922183b 100644 --- a/include/crypto/ctype.h +++ b/include/crypto/ctype.h @@ -22,6 +22,8 @@ # define OSSL_CRYPTO_CTYPE_H # pragma once +# include + # 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))