From: Nick Mathewson Date: Tue, 10 Feb 2009 21:40:12 +0000 (+0000) Subject: Do not use ctypes functions in cases when we need the "net" locale. X-Git-Tag: release-2.0.1-alpha~72 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cd731b77d7e6d0398010ff45bb80e9a3534eaccc;p=libevent Do not use ctypes functions in cases when we need the "net" locale. This patch adds a new set of EVUTIL_IS* functions to replace use of the ctypes is* functions in all cases where we care about characters' interpretations in net ascii rather than in the locale. For example, when we're working with DNS hostnames, we don't want to do the 0x20 hack on non-ascii characters, even if the host thinks they should be isalpha. svn:r1114 --- diff --git a/evdns.c b/evdns.c index 7b76ee39..01ff0bde 100644 --- a/evdns.c +++ b/evdns.c @@ -95,7 +95,6 @@ #endif #include #include -#include #include #include @@ -107,6 +106,7 @@ #include "ipv6-internal.h" #include "util-internal.h" #ifdef WIN32 +#include #include #include #include @@ -360,9 +360,6 @@ static int strtoint(const char *const str); #define CLOSE_SOCKET(s) EVUTIL_CLOSESOCKET(s) -#define ISSPACE(c) isspace((int)(unsigned char)(c)) -#define ISDIGIT(c) isdigit((int)(unsigned char)(c)) - static const char * debug_ntoa(u32 address) { @@ -2353,10 +2350,6 @@ string_num_dots(const char *s) { return count; } -/* Helper: provide a working isalpha implementation on platforms with funny - * ideas about character types and isalpha behavior. */ -#define ISALPHA(c) isalpha((int)(unsigned char)(c)) - static struct evdns_request * request_new(struct evdns_base *base, int type, const char *name, int flags, evdns_callback_type callback, void *user_ptr) { @@ -2389,7 +2382,7 @@ request_new(struct evdns_base *base, int type, const char *name, int flags, strlcpy(namebuf, name, sizeof(namebuf)); rand_bytes_function(randbits, (name_len+7)/8); for (i = 0; i < name_len; ++i) { - if (ISALPHA(namebuf[i])) { + if (EVUTIL_ISALPHA(namebuf[i])) { if ((randbits[i >> 3] & (1<<(i & 7)))) namebuf[i] |= 0x20; else @@ -3079,10 +3072,10 @@ evdns_nameserver_ip_add_line(struct evdns_base *base, const char *ips) { char *buf; int r; while (*ips) { - while (ISSPACE(*ips) || *ips == ',' || *ips == '\t') + while (isspace(*ips) || *ips == ',' || *ips == '\t') ++ips; addr = ips; - while (ISDIGIT(*ips) || *ips == '.' || *ips == ':') + while (isdigit(*ips) || *ips == '.' || *ips == ':') ++ips; buf = mm_malloc(ips-addr+1); if (!buf) return 4; diff --git a/evrpc.c b/evrpc.c index 25e7bf78..a925ffb4 100644 --- a/evrpc.c +++ b/evrpc.c @@ -53,7 +53,6 @@ #include #include -#include "util-internal.h" #include "event2/event.h" #include "event2/event_struct.h" #include "evrpc.h" @@ -63,7 +62,8 @@ #include "event2/tag.h" #include "event2/http_struct.h" #include "event2/http_compat.h" -#include "evutil.h" +#include "event2/util.h" +#include "util-internal.h" #include "log-internal.h" #include "mm-internal.h" diff --git a/evutil.c b/evutil.c index e3ddb96a..38095592 100644 --- a/evutil.c +++ b/evutil.c @@ -50,7 +50,6 @@ #endif #include #include -#include #include #ifdef _EVENT_HAVE_ARPA_INET_H #include @@ -68,6 +67,7 @@ #endif #include "event2/util.h" +#include "util-internal.h" #include "log-internal.h" #include "strlcpy-internal.h" @@ -469,9 +469,6 @@ evutil_inet_ntop(int af, const void *src, char *dst, size_t len) #endif } -#define ISDIGIT(c) isdigit((int)(unsigned char)(c)) -#define ISXDIGIT(c) isxdigit((int)(unsigned char)(c)) - int evutil_inet_pton(int af, const char *src, void *dst) { @@ -504,7 +501,7 @@ evutil_inet_pton(int af, const char *src, void *dst) else { int byte1,byte2,byte3,byte4; char more; - for (eow = dot-1; eow >= src && ISDIGIT(*eow); --eow) + for (eow = dot-1; eow >= src && EVUTIL_ISDIGIT(*eow); --eow) ; ++eow; @@ -529,7 +526,7 @@ evutil_inet_pton(int af, const char *src, void *dst) while (src < eow) { if (i > 7) return 0; - if (ISXDIGIT(*src)) { + if (EVUTIL_ISXDIGIT(*src)) { char *next; long r = strtol(src, &next, 16); if (next > 4+src) @@ -679,3 +676,59 @@ evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int o return 0; } } + +/* Tables to implement ctypes-replacement EVUTIL_IS*() functions. Each table + * has 256 bits to look up whether a character is in some set or not. This + * fails on non-ASCII platforms, but so does every other place where we + * take a char and write it onto the network. + **/ +const ev_uint32_t EVUTIL_ISALPHA_TABLE[8] = + { 0, 0, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISALNUM_TABLE[8] = + { 0, 0x3ff0000, 0x7fffffe, 0x7fffffe, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISSPACE_TABLE[8] = { 0x3e00, 0x1, 0, 0, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISXDIGIT_TABLE[8] = + { 0, 0x3ff0000, 0x7e, 0x7e, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISDIGIT_TABLE[8] = { 0, 0x3ff0000, 0, 0, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISPRINT_TABLE[8] = + { 0, 0xffffffff, 0xffffffff, 0x7fffffff, 0, 0, 0, 0x0 }; +const ev_uint32_t EVUTIL_ISUPPER_TABLE[8] = { 0, 0, 0x7fffffe, 0, 0, 0, 0, 0 }; +const ev_uint32_t EVUTIL_ISLOWER_TABLE[8] = { 0, 0, 0, 0x7fffffe, 0, 0, 0, 0 }; +/* Upper-casing and lowercasing tables to map characters to upper/lowercase + * equivalents. */ +const char EVUTIL_TOUPPER_TABLE[256] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, + 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, + 96,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, + 80,81,82,83,84,85,86,87,88,89,90,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, +}; +const char EVUTIL_TOLOWER_TABLE[256] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, + 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, + 64,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,91,92,93,94,95, + 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, + 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, +}; diff --git a/http.c b/http.c index 5349c717..18984368 100644 --- a/http.c +++ b/http.c @@ -63,7 +63,6 @@ #endif #include -#include #include #include #include @@ -2125,8 +2124,8 @@ evhttp_decode_uri_internal(const char *uri, size_t length, char *ret) in_query = 1; } else if (c == '+' && in_query) { c = ' '; - } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) && - isxdigit((unsigned char)uri[i+2])) { + } else if (c == '%' && EVUTIL_ISXDIGIT(uri[i+1]) && + EVUTIL_ISXDIGIT(uri[i+2])) { char tmp[] = { uri[i+1], uri[i+2], '\0' }; c = (char)strtol(tmp, NULL, 16); i += 2; @@ -2254,7 +2253,7 @@ prefix_suffix_match(const char *pattern, const char *name, int ignorecase) default: if (c != *name) { if (!ignorecase || - tolower(c) != tolower(*name)) + EVUTIL_TOLOWER(c) != EVUTIL_TOLOWER(*name)) return (0); } ++name; diff --git a/util-internal.h b/util-internal.h index 13b98e0e..b429f57e 100644 --- a/util-internal.h +++ b/util-internal.h @@ -74,6 +74,30 @@ extern "C" { #define socklen_t _EVENT_socklen_t #endif +/* Locale-independent replacements for some ctypes functions. Use these + * when you care about ASCII's notion of character types, because you are about + * to send those types onto the wire. + */ +#define DECLARE_CTYPE_FN(name) \ + static int EVUTIL_##name(char c); \ + extern const ev_uint32_t EVUTIL_##name##_TABLE[]; \ + static inline int EVUTIL_##name(char c) { \ + ev_uint8_t u = c; \ + return !!(EVUTIL_##name##_TABLE[(u >> 5) & 7] & (1 << (u & 31))); \ + } +DECLARE_CTYPE_FN(ISALPHA) +DECLARE_CTYPE_FN(ISALNUM) +DECLARE_CTYPE_FN(ISSPACE) +DECLARE_CTYPE_FN(ISDIGIT) +DECLARE_CTYPE_FN(ISXDIGIT) +DECLARE_CTYPE_FN(ISPRINT) +DECLARE_CTYPE_FN(ISLOWER) +DECLARE_CTYPE_FN(ISUPPER) +extern const char EVUTIL_TOUPPER_TABLE[]; +extern const char EVUTIL_TOLOWER_TABLE[]; +#define EVUTIL_TOLOWER(c) (EVUTIL_TOLOWER_TABLE[(ev_uint8_t)c]) +#define EVUTIL_TOUPPER(c) (EVUTIL_TOUPPER_TABLE[(ev_uint8_t)c]) + #ifdef __cplusplus } #endif