From c58b95f2976a0563884a09a6aafb5e1332e3ca3b Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Thu, 10 Sep 2020 00:15:29 -0400 Subject: [PATCH] [core] light_isupper(), light_islower() more efficient char checks (replace one comparision and one branch with one subtraction) --- src/array.c | 4 ++-- src/buffer.c | 16 +++++++--------- src/buffer.h | 9 ++++++--- src/burl.c | 4 ++-- src/h2.c | 4 ++-- src/http_auth.c | 10 +++++----- src/http_header.c | 2 +- src/mod_secdownload.c | 13 ++----------- src/mod_userdir.c | 2 +- src/request.c | 4 ++-- 10 files changed, 30 insertions(+), 38 deletions(-) diff --git a/src/array.c b/src/array.c index 781643a3..995f8ac7 100644 --- a/src/array.c +++ b/src/array.c @@ -101,8 +101,8 @@ static int array_caseless_compare(const char * const a, const char * const b, co if (ca == cb) continue; /* always lowercase for transitive results */ - if (ca >= 'A' && ca <= 'Z') ca |= 32; - if (cb >= 'A' && cb <= 'Z') cb |= 32; + if (light_isupper(ca)) ca |= 0x20; + if (light_isupper(cb)) cb |= 0x20; if (ca == cb) continue; return (int)(ca - cb); diff --git a/src/buffer.c b/src/buffer.c index b3b90454..d10b4b21 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -327,9 +327,9 @@ int buffer_eq_icase_ssn(const char * const a, const char * const b, const size_t if (ca != cb) { ca |= 0x20; cb |= 0x20; - if (ca != cb) return 0; - if (ca < 'a' || 'z' < ca) return 0; - if (cb < 'a' || 'z' < cb) return 0; + if (ca != cb) return 0; + if (!light_islower(ca)) return 0; + if (!light_islower(cb)) return 0; } } return 1; @@ -921,19 +921,17 @@ void buffer_path_simplify(buffer *dest, buffer *src) } void buffer_to_lower(buffer * const b) { - char * const s = b->ptr; + unsigned char * const restrict s = (unsigned char *)b->ptr; for (uint32_t i = 0; i < b->used; ++i) { - char c = s[i]; - if (c >= 'A' && c <= 'Z') s[i] |= 0x20; + if (light_isupper(s[i])) s[i] |= 0x20; } } void buffer_to_upper(buffer * const b) { - char * const s = b->ptr; + unsigned char * const restrict s = (unsigned char *)b->ptr; for (uint32_t i = 0; i < b->used; ++i) { - char c = s[i]; - if (c >= 'a' && c <= 'z') s[i] &= ~0x20; + if (light_islower(s[i])) s[i] &= 0xdf; } } diff --git a/src/buffer.h b/src/buffer.h index f7612bff..989164f2 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -193,19 +193,19 @@ char int2hex(char i); __attribute_pure__ static inline int light_isdigit(int c); static inline int light_isdigit(int c) { - return (c >= '0' && c <= '9'); + return ((uint32_t)c-'0' <= '9'-'0'); } __attribute_pure__ static inline int light_isxdigit(int c); static inline int light_isxdigit(int c) { - return light_isdigit(c) || (c |= 32, c >= 'a' && c <= 'f'); + return light_isdigit(c) || (((uint32_t)c | 0x20)-'a' <= 'f'-'a'); } __attribute_pure__ static inline int light_isalpha(int c); static inline int light_isalpha(int c) { - return (c |= 32, c >= 'a' && c <= 'z'); + return (((uint32_t)c | 0x20)-'a' <= 'z'-'a'); } __attribute_pure__ @@ -214,6 +214,9 @@ static inline int light_isalnum(int c) { return light_isdigit(c) || light_isalpha(c); } +#define light_isupper(c) ((uint32_t)(c)-'A' <= 'Z'-'A') +#define light_islower(c) ((uint32_t)(c)-'a' <= 'z'-'a') + __attribute_pure__ static inline uint32_t buffer_string_length(const buffer *b); /* buffer string length without terminating 0 */ diff --git a/src/burl.c b/src/burl.c index af7f18df..5e2e8196 100644 --- a/src/burl.c +++ b/src/burl.c @@ -463,7 +463,7 @@ static void burl_offset_tolower (buffer * const b, const size_t off) { /*(skips over all percent-encodings, including encoding of alpha chars)*/ for (char *p = b->ptr+off; p[0]; ++p) { - if (p[0] >= 'A' && p[0] <= 'Z') p[0] |= 0x20; + if (light_isupper(p[0])) p[0] |= 0x20; else if (p[0]=='%' && light_isxdigit(p[1]) && light_isxdigit(p[2])) p+=2; } @@ -474,7 +474,7 @@ static void burl_offset_toupper (buffer * const b, const size_t off) { /*(skips over all percent-encodings, including encoding of alpha chars)*/ for (char *p = b->ptr+off; p[0]; ++p) { - if (p[0] >= 'a' && p[0] <= 'z') p[0] &= 0xdf; + if (light_islower(p[0])) p[0] &= 0xdf; else if (p[0]=='%' && light_isxdigit(p[1]) && light_isxdigit(p[2])) p+=2; } diff --git a/src/h2.c b/src/h2.c index fdf58d5a..98f3ae68 100644 --- a/src/h2.c +++ b/src/h2.c @@ -1644,7 +1644,7 @@ h2_send_headers (request_st * const r, connection * const con) * end of value buffer */ char * const v = buffer_string_prepare_append(&ds->value, klen); for (uint32_t j = 0; j < klen; ++j) - v[j] = (k[j] < 'A' || k[j] > 'Z') ? k[j] : (k[j] | 0x20); + v[j] = !light_isupper(k[j]) ? k[j] : (k[j] | 0x20); /*buffer_commit(&ds->value, klen);*//*(not necessary; truncated below)*/ uint32_t voff = 0; @@ -1908,7 +1908,7 @@ h2_send_end_stream_trailers (request_st * const r, connection * const con, const const char * const colon = memchr(k, ':', ptr+hoff[i+1]-k); if (NULL == colon) continue; do { - if (*k >= 'A' && *k <= 'Z') *k |= 0x20; + if (light_isupper(*k)) *k |= 0x20; } while (++k != colon); } diff --git a/src/http_auth.c b/src/http_auth.c index 176a50f5..4bc4f70c 100644 --- a/src/http_auth.c +++ b/src/http_auth.c @@ -192,10 +192,10 @@ int http_auth_digest_hex2bin (const char *hexstr, size_t len, unsigned char *bin int hi = hexstr[i]; int lo = hexstr[i+1]; if ('0' <= hi && hi <= '9') hi -= '0'; - else if ((hi |= 0x20), 'a' <= hi && hi <= 'f') hi += -'a' + 10; + else if ((uint32_t)(hi |= 0x20)-'a' <= 'f'-'a')hi += -'a' + 10; else return -1; if ('0' <= lo && lo <= '9') lo -= '0'; - else if ((lo |= 0x20), 'a' <= lo && lo <= 'f') lo += -'a' + 10; + else if ((uint32_t)(lo |= 0x20)-'a' <= 'f'-'a')lo += -'a' + 10; else return -1; bin[(i >> 1)] = (unsigned char)((hi << 4) | lo); } @@ -209,9 +209,9 @@ int http_auth_md5_hex2lc (char *md5hex) int i; for (i = 0; md5hex[i]; ++i) { int c = md5hex[i]; - if ('0' <= c && c <= '9') continue; - else if ((c |= 0x20), 'a' <= c && c <= 'f') md5hex[i] = c; - else return -1; + if ('0' <= c && c <= '9') continue; + else if ((uint32_t)(c |= 0x20)-'a' <= 'f'-'a') md5hex[i] = c; + else return -1; } return (32 == i) ? 0 : -1; /*(Note: char *md5hex must be a 32-char string)*/ } diff --git a/src/http_header.c b/src/http_header.c index 5f206692..d382cc87 100644 --- a/src/http_header.c +++ b/src/http_header.c @@ -195,7 +195,7 @@ void http_header_response_insert(request_st * const r, enum http_header_e id, co r->resp_header_repeated = 1; char * const h = buffer_string_prepare_append(vb, klen + vlen + 2); for (uint32_t i = 0; i < klen; ++i) - h[i] = (k[i] < 'A' || k[i] > 'Z') ? k[i] : (k[i] | 0x20); + h[i] = !light_isupper(k[i]) ? k[i] : (k[i] | 0x20); buffer_commit(vb, klen); } else diff --git a/src/mod_secdownload.c b/src/mod_secdownload.c index 4c00a4d5..afa343cb 100644 --- a/src/mod_secdownload.c +++ b/src/mod_secdownload.c @@ -477,12 +477,8 @@ static int is_hex_len(const char *str, size_t len) { for (i = 0; i < len && *str; i++, str++) { /* illegal characters */ - if (!((*str >= '0' && *str <= '9') || - (*str >= 'a' && *str <= 'f') || - (*str >= 'A' && *str <= 'F')) - ) { + if (!light_isxdigit(*str)) return 0; - } } return i == len; @@ -502,13 +498,8 @@ static int is_base64_len(const char *str, size_t len) { for (i = 0; i < len && *str; i++, str++) { /* illegal characters */ - if (!((*str >= '0' && *str <= '9') || - (*str >= 'a' && *str <= 'z') || - (*str >= 'A' && *str <= 'Z') || - (*str == '-') || (*str == '_')) - ) { + if (!(light_isalnum(*str) || *str == '-' || *str == '_')) return 0; - } } return i == len; diff --git a/src/mod_userdir.c b/src/mod_userdir.c index 45945a6d..73552ded 100644 --- a/src/mod_userdir.c +++ b/src/mod_userdir.c @@ -179,7 +179,7 @@ static handler_t mod_userdir_docroot_construct(request_st * const r, plugin_data if (r->conf.force_lowercase_filenames) { for (size_t i = 0; i < ulen; ++i) { - if (u[i] >= 'A' && u[i] <= 'Z') u[i] |= 0x20; + if (light_isupper(u[i])) u[i] |= 0x20; } } diff --git a/src/request.c b/src/request.c index 9f646e26..48702913 100644 --- a/src/request.c +++ b/src/request.c @@ -784,9 +784,9 @@ http_request_parse_header (request_st * const restrict r, http_header_parse_ctx (hpctx->http_parseopts & HTTP_PARSEOPT_HEADER_STRICT); for (uint32_t j = 0; j < klen; ++j) { - if ((k[j] >= 'a' && k[j] <= 'z') || k[j] == '-') + if (light_islower(k[j]) || k[j] == '-') continue; /*(common cases)*/ - if (k[j] >= 'A' && k[j] <= 'Z') + if (light_isupper(k[j])) return 400; if (0 != http_request_parse_header_other(r, k+j, klen-j, http_header_strict))