"Fossies" - the Fresh Open Source Software Archive

Member "memcached-1.6.15/util.c" (21 Feb 2022, 6562 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "util.c" see the Fossies "Dox" file reference documentation.

    1 #include <stdio.h>
    2 #include <assert.h>
    3 #include <ctype.h>
    4 #include <errno.h>
    5 #include <string.h>
    6 #include <stdlib.h>
    7 #include <stdarg.h>
    8 
    9 #include "memcached.h"
   10 
   11 static char *uriencode_map[256];
   12 static char uriencode_str[768];
   13 
   14 void uriencode_init(void) {
   15     int x;
   16     char *str = uriencode_str;
   17     for (x = 0; x < 256; x++) {
   18         if (isalnum(x) || x == '-' || x == '.' || x == '_' || x == '~') {
   19             uriencode_map[x] = NULL;
   20         } else {
   21             snprintf(str, 4, "%%%02hhX", (unsigned char)x);
   22             uriencode_map[x] = str;
   23             str += 3; /* lobbing off the \0 is fine */
   24         }
   25     }
   26 }
   27 
   28 bool uriencode(const char *src, char *dst, const size_t srclen, const size_t dstlen) {
   29     int x;
   30     size_t d = 0;
   31     for (x = 0; x < srclen; x++) {
   32         if (d + 4 > dstlen)
   33             return false;
   34         if (uriencode_map[(unsigned char) src[x]] != NULL) {
   35             memcpy(&dst[d], uriencode_map[(unsigned char) src[x]], 3);
   36             d += 3;
   37         } else {
   38             dst[d] = src[x];
   39             d++;
   40         }
   41     }
   42     dst[d] = '\0';
   43     return true;
   44 }
   45 
   46 /* Avoid warnings on solaris, where isspace() is an index into an array, and gcc uses signed chars */
   47 #define xisspace(c) isspace((unsigned char)c)
   48 
   49 bool safe_strtoull(const char *str, uint64_t *out) {
   50     assert(out != NULL);
   51     errno = 0;
   52     *out = 0;
   53     char *endptr;
   54     unsigned long long ull = strtoull(str, &endptr, 10);
   55     if ((errno == ERANGE) || (str == endptr)) {
   56         return false;
   57     }
   58 
   59     if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) {
   60         if ((long long) ull < 0) {
   61             /* only check for negative signs in the uncommon case when
   62              * the unsigned number is so big that it's negative as a
   63              * signed number. */
   64             if (strchr(str, '-') != NULL) {
   65                 return false;
   66             }
   67         }
   68         *out = ull;
   69         return true;
   70     }
   71     return false;
   72 }
   73 
   74 /* Could macro this. Decided to keep this unrolled for safety rather than add
   75  * the base parameter to all callers. Very few places need to parse a number
   76  * outside of base 10, currently exactly once, so splitting this up should
   77  * help avoid typo bugs.
   78  */
   79 bool safe_strtoull_hex(const char *str, uint64_t *out) {
   80     assert(out != NULL);
   81     errno = 0;
   82     *out = 0;
   83     char *endptr;
   84     unsigned long long ull = strtoull(str, &endptr, 16);
   85     if ((errno == ERANGE) || (str == endptr)) {
   86         return false;
   87     }
   88 
   89     if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) {
   90         if ((long long) ull < 0) {
   91             /* only check for negative signs in the uncommon case when
   92              * the unsigned number is so big that it's negative as a
   93              * signed number. */
   94             if (strchr(str, '-') != NULL) {
   95                 return false;
   96             }
   97         }
   98         *out = ull;
   99         return true;
  100     }
  101     return false;
  102 }
  103 
  104 bool safe_strtoll(const char *str, int64_t *out) {
  105     assert(out != NULL);
  106     errno = 0;
  107     *out = 0;
  108     char *endptr;
  109     long long ll = strtoll(str, &endptr, 10);
  110     if ((errno == ERANGE) || (str == endptr)) {
  111         return false;
  112     }
  113 
  114     if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) {
  115         *out = ll;
  116         return true;
  117     }
  118     return false;
  119 }
  120 
  121 bool safe_strtoul(const char *str, uint32_t *out) {
  122     char *endptr = NULL;
  123     unsigned long l = 0;
  124     assert(out);
  125     assert(str);
  126     *out = 0;
  127     errno = 0;
  128 
  129     l = strtoul(str, &endptr, 10);
  130     if ((errno == ERANGE) || (str == endptr)) {
  131         return false;
  132     }
  133 
  134     if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) {
  135         if ((long) l < 0) {
  136             /* only check for negative signs in the uncommon case when
  137              * the unsigned number is so big that it's negative as a
  138              * signed number. */
  139             if (strchr(str, '-') != NULL) {
  140                 return false;
  141             }
  142         }
  143         *out = l;
  144         return true;
  145     }
  146 
  147     return false;
  148 }
  149 
  150 bool safe_strtol(const char *str, int32_t *out) {
  151     assert(out != NULL);
  152     errno = 0;
  153     *out = 0;
  154     char *endptr;
  155     long l = strtol(str, &endptr, 10);
  156     if ((errno == ERANGE) || (str == endptr)) {
  157         return false;
  158     }
  159 
  160     if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) {
  161         *out = l;
  162         return true;
  163     }
  164     return false;
  165 }
  166 
  167 bool safe_strtod(const char *str, double *out) {
  168     assert(out != NULL);
  169     errno = 0;
  170     *out = 0;
  171     char *endptr;
  172     double d = strtod(str, &endptr);
  173     if ((errno == ERANGE) || (str == endptr)) {
  174         return false;
  175     }
  176 
  177     if (xisspace(*endptr) || (*endptr == '\0' && endptr != str)) {
  178         *out = d;
  179         return true;
  180     }
  181     return false;
  182 }
  183 
  184 // slow, safe function for copying null terminated buffers.
  185 // ensures null terminator set on destination buffer. copies at most dstmax-1
  186 // non-null bytes.
  187 // Explicitly avoids over-reading src while looking for the null byte.
  188 // returns true if src was fully copied.
  189 // returns false if src was truncated into dst.
  190 bool safe_strcpy(char *dst, const char *src, const size_t dstmax) {
  191    size_t x;
  192 
  193    for (x = 0; x < dstmax - 1 && src[x] != '\0'; x++) {
  194         dst[x] = src[x];
  195    }
  196 
  197    dst[x] = '\0';
  198 
  199    if (src[x] == '\0') {
  200        return true;
  201    } else {
  202        return false;
  203    }
  204 }
  205 
  206 bool safe_memcmp(const void *a, const void *b, size_t len) {
  207     const volatile unsigned char *ua = (const volatile unsigned char *)a;
  208     const volatile unsigned char *ub = (const volatile unsigned char *)b;
  209     int delta = 0;
  210     size_t x;
  211 
  212     for (x = 0; x < len; x++) {
  213         delta |= ua[x] ^ ub[x];
  214     }
  215 
  216     if (delta == 0) {
  217         return true;
  218     } else {
  219         return false;
  220     }
  221 }
  222 
  223 void vperror(const char *fmt, ...) {
  224     int old_errno = errno;
  225     char buf[1024];
  226     va_list ap;
  227 
  228     va_start(ap, fmt);
  229     if (vsnprintf(buf, sizeof(buf), fmt, ap) == -1) {
  230         buf[sizeof(buf) - 1] = '\0';
  231     }
  232     va_end(ap);
  233 
  234     errno = old_errno;
  235 
  236     perror(buf);
  237 }
  238 
  239 #ifndef HAVE_HTONLL
  240 static uint64_t mc_swap64(uint64_t in) {
  241 #ifdef ENDIAN_LITTLE
  242     /* Little endian, flip the bytes around until someone makes a faster/better
  243     * way to do this. */
  244     int64_t rv = 0;
  245     int i = 0;
  246      for(i = 0; i<8; i++) {
  247         rv = (rv << 8) | (in & 0xff);
  248         in >>= 8;
  249      }
  250     return rv;
  251 #else
  252     /* big-endian machines don't need byte swapping */
  253     return in;
  254 #endif
  255 }
  256 
  257 uint64_t ntohll(uint64_t val) {
  258    return mc_swap64(val);
  259 }
  260 
  261 uint64_t htonll(uint64_t val) {
  262    return mc_swap64(val);
  263 }
  264 #endif
  265