]> granicus.if.org Git - libevent/commitdiff
Do not use ctypes functions in cases when we need the "net" locale.
authorNick Mathewson <nickm@torproject.org>
Tue, 10 Feb 2009 21:40:12 +0000 (21:40 +0000)
committerNick Mathewson <nickm@torproject.org>
Tue, 10 Feb 2009 21:40:12 +0000 (21:40 +0000)
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

evdns.c
evrpc.c
evutil.c
http.c
util-internal.h

diff --git a/evdns.c b/evdns.c
index 7b76ee395fa33d76bb28a0d3769f86d2196ebf6f..01ff0bdef065d9898328a8067bf6b1ed7b97d521 100644 (file)
--- a/evdns.c
+++ b/evdns.c
@@ -95,7 +95,6 @@
 #endif
 #include <limits.h>
 #include <sys/stat.h>
-#include <ctype.h>
 #include <stdio.h>
 #include <stdarg.h>
 
 #include "ipv6-internal.h"
 #include "util-internal.h"
 #ifdef WIN32
+#include <ctype.h>
 #include <winsock2.h>
 #include <windows.h>
 #include <ws2tcpip.h>
@@ -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 25e7bf780c29cb497f7fdc239a5bbd15e9542248..a925ffb44decfe6322f0926006146cdc0d84c9c3 100644 (file)
--- a/evrpc.c
+++ b/evrpc.c
@@ -53,7 +53,6 @@
 #include <string.h>
 #include <assert.h>
 
-#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"
 
index e3ddb96aebb58dd9a4332c81a1ecdd9ec3220aa5..38095592f0b5f59d4cac1ca984cb4b13d94d7c9b 100644 (file)
--- a/evutil.c
+++ b/evutil.c
@@ -50,7 +50,6 @@
 #endif
 #include <errno.h>
 #include <stdio.h>
-#include <ctype.h>
 #include <string.h>
 #ifdef _EVENT_HAVE_ARPA_INET_H
 #include <arpa/inet.h>
@@ -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 5349c717efd480d002a482132a6d38769e022527..189843688101f4fdc7bf07502d65d46918339cfa 100644 (file)
--- a/http.c
+++ b/http.c
@@ -63,7 +63,6 @@
 #endif
 
 #include <assert.h>
-#include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -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;
index 13b98e0e8258dd5e43229d964c917eeead7348b5..b429f57edd315dd57de39970fdc0e6655edc3d04 100644 (file)
@@ -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