diff --git a/configure.in b/configure.in index dfd26037be..748a6cdf82 100644 --- a/configure.in +++ b/configure.in @@ -297,12 +297,11 @@ dnl These headers are not essential AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h sys/time.h sys/resource.h pthread.h stddef.h inttypes.h) -AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit setrlimit strlcat strlcpy strtoull getpwnam ftello pthread_create getaddrinfo localtime_r gmtime_r event_get_version event_get_method event_set_log_callback) +AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit setrlimit strlcat strlcpy strtoull getpwnam ftello pthread_create getaddrinfo localtime_r gmtime_r event_get_version event_get_method event_set_log_callback memmem) AC_FUNC_FSEEKO AC_CHECK_MEMBERS([struct timeval.tv_sec]) - dnl In case we aren't given a working stdint.h, we'll need to grow our own. dnl Watch out. diff --git a/src/common/compat.c b/src/common/compat.c index 85db2b6ad4..f6fdda6e0a 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -13,7 +13,9 @@ const char compat_c_id[] = "$Id$"; * the platform. **/ -/* This is required on rh7 to make strptime not complain. */ +/* This is required on rh7 to make strptime not complain. + * We also need it to make memmem get defined (where available) + */ #define _GNU_SOURCE #include "orconfig.h" @@ -134,6 +136,38 @@ tor_vsnprintf(char *str, size_t size, const char *format, va_list args) return r; } +/** Given hlen bytes at haystack and nlen bytes at + * needle, return a pointer to the first occurence of the needle + * within the haystack, or NULL if there is no such occurrence. + * + * Requires that nlen be greater than zero. + */ +const void * +tor_memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) +{ +#if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) + tor_assert(nlen); + return memmem(haystack, hlen, needle, nlen); +#else + /* This isn't as fast as the GLIBC implementation, but it doesn't need to be. */ + const void *p, *end; + char first; + tor_assert(nlen); + + p = haystack; + end = haystack + hlen; + first = *(const char*)needle; + while ((p = memchr(p, first, end-p))) { + if (end-p >= nlen) + return NULL; + if (!memcmp(p, needle, nlen)) + return p; + ++p; + } + return NULL; +#endif +} + /** Take a filename and return a pointer to its final element. This * function is called on __FILE__ to fix a MSVC nit where __FILE__ * contains the full path to the file. This is bad, because it diff --git a/src/common/compat.h b/src/common/compat.h index 8f44e93857..dbf8828ab3 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -87,6 +87,9 @@ int tor_snprintf(char *str, size_t size, const char *format, ...) CHECK_PRINTF(3,4); int tor_vsnprintf(char *str, size_t size, const char *format, va_list args); +const void *tor_memmem(const void *haystack, size_t hlen, const void *needle, + size_t nlen); + #define TOR_ISAPLHA(c) isalpha((int)(unsigned char)(c)) #define TOR_ISALNUM(c) isalnum((int)(unsigned char)(c)) #define TOR_ISSPACE(c) isspace((int)(unsigned char)(c))