diff options
author | Nick Mathewson <nickm@torproject.org> | 2010-10-11 10:50:47 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2010-10-11 10:50:47 -0400 |
commit | 8f76f31761f051d5b6a3280462db6adf95b19233 (patch) | |
tree | b9a4daadf14df6db79a5ecb978a3bedd20e3730a /src/common/util.c | |
parent | 45ce1f678fa3de4634d29415d850eb2723440bca (diff) | |
download | tor-8f76f31761f051d5b6a3280462db6adf95b19233.tar.gz tor-8f76f31761f051d5b6a3280462db6adf95b19233.zip |
Make tor_sscanf handle %x
Diffstat (limited to 'src/common/util.c')
-rw-r--r-- | src/common/util.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/src/common/util.c b/src/common/util.c index b5a3ade2bd..fd6956c3a4 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -2498,18 +2498,21 @@ digit_to_num(char d) * success, store the result in <b>out</b>, advance bufp to the next * character, and return 0. On failure, return -1. */ static int -scan_unsigned(const char **bufp, unsigned *out, int width) +scan_unsigned(const char **bufp, unsigned *out, int width, int base) { unsigned result = 0; int scanned_so_far = 0; + const int hex = base==16; + tor_assert(base == 10 || base == 16); if (!bufp || !*bufp || !out) return -1; if (width<0) width=MAX_SCANF_WIDTH; - while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) { - int digit = digit_to_num(*(*bufp)++); - unsigned new_result = result * 10 + digit; + while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp)) + && scanned_so_far < width) { + int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++); + unsigned new_result = result * base + digit; if (new_result > UINT32_MAX || new_result < result) return -1; /* over/underflow. */ result = new_result; @@ -2571,11 +2574,12 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) if (!width) /* No zero-width things. */ return -1; } - if (*pattern == 'u') { + if (*pattern == 'u' || *pattern == 'x') { unsigned *u = va_arg(ap, unsigned *); + const int base = (*pattern == 'u') ? 10 : 16; if (!*buf) return n_matched; - if (scan_unsigned(&buf, u, width)<0) + if (scan_unsigned(&buf, u, width, base)<0) return n_matched; ++pattern; ++n_matched; @@ -2612,9 +2616,9 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap) /** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b> * and store the results in the corresponding argument fields. Differs from - * sscanf in that it: Only handles %u and %Ns. Does not handle arbitrarily - * long widths. %u does not consume any space. Is locale-independent. - * Returns -1 on malformed patterns. + * sscanf in that it: Only handles %u and %x and %Ns. Does not handle + * arbitrarily long widths. %u and %x do not consume any space. Is + * locale-independent. Returns -1 on malformed patterns. * * (As with other locale-independent functions, we need this to parse data that * is in ASCII without worrying that the C library's locale-handling will make |