Skip to content

Commit

Permalink
Do not use ctypes functions in cases when we need the "net" locale.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
nmathewson committed Feb 10, 2009
1 parent 1ed2704 commit cd731b7
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 23 deletions.
15 changes: 4 additions & 11 deletions evdns.c
Expand Up @@ -95,7 +95,6 @@
#endif
#include <limits.h>
#include <sys/stat.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

Expand All @@ -107,6 +106,7 @@
#include "ipv6-internal.h"
#include "util-internal.h"
#ifdef WIN32
#include <ctype.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions evrpc.c
Expand Up @@ -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"
Expand All @@ -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"

Expand Down
65 changes: 59 additions & 6 deletions evutil.c
Expand Up @@ -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>
Expand All @@ -68,6 +67,7 @@
#endif

#include "event2/util.h"
#include "util-internal.h"
#include "log-internal.h"

#include "strlcpy-internal.h"
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;

Expand All @@ -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)
Expand Down Expand Up @@ -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,
};
7 changes: 3 additions & 4 deletions http.c
Expand Up @@ -63,7 +63,6 @@
#endif

#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
24 changes: 24 additions & 0 deletions util-internal.h
Expand Up @@ -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
Expand Down

0 comments on commit cd731b7

Please sign in to comment.