From bf9712678fc9ec85bf2ac54407e16d76aa22e7b6 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 15 Nov 2010 10:18:10 -0800 Subject: [PATCH] util: Add function hexits_value() for parsing multiple hex digits. Suggested-by: Justin Pettit --- lib/json.c | 12 ++++------- lib/nx-match.c | 8 +++----- lib/ofp-parse.c | 13 +++++------- lib/sha1.c | 8 +++++--- lib/util.c | 27 ++++++++++++++++++++++++ lib/util.h | 1 + lib/uuid.c | 50 +++++++++++++++++++++++++++++++-------------- tests/test-aes128.c | 9 ++++---- 8 files changed, 84 insertions(+), 44 deletions(-) diff --git a/lib/json.c b/lib/json.c index 5887f677a..0a8bca278 100644 --- a/lib/json.c +++ b/lib/json.c @@ -746,19 +746,15 @@ json_lex_number(struct json_parser *p) static const char * json_lex_4hex(const char *cp, const char *end, int *valuep) { - int value, i; + unsigned int value; if (cp + 4 > end) { return "quoted string ends within \\u escape"; } - value = 0; - for (i = 0; i < 4; i++) { - unsigned char c = *cp++; - if (!isxdigit(c)) { - return "malformed \\u escape"; - } - value = (value << 4) | hexit_value(c); + value = hexits_value(cp, 4, NULL); + if (value == UINT_MAX) { + return "malformed \\u escape"; } if (!value) { return "null bytes not supported in quoted strings"; diff --git a/lib/nx-match.c b/lib/nx-match.c index 12ea4fb8c..9f869a765 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -747,17 +747,15 @@ static const char * parse_hex_bytes(struct ofpbuf *b, const char *s, unsigned int n) { while (n--) { - int low, high; uint8_t byte; + bool ok; s += strspn(s, " "); - low = hexit_value(*s); - high = low < 0 ? low : hexit_value(s[1]); - if (low < 0 || high < 0) { + byte = hexits_value(s, 2, &ok); + if (!ok) { ovs_fatal(0, "%.2s: hex digits expected", s); } - byte = 16 * low + high; ofpbuf_put(b, &byte, 1); s += 2; } diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 6b53f2655..20440323f 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -289,8 +289,8 @@ str_to_action(char *str, struct ofpbuf *b) b->size -= sizeof nan->note; while (arg && *arg != '\0') { - int high, low; uint8_t byte; + bool ok; if (*arg == '.') { arg++; @@ -299,16 +299,13 @@ str_to_action(char *str, struct ofpbuf *b) break; } - high = hexit_value(*arg++); - if (high >= 0) { - low = hexit_value(*arg++); - } - if (high < 0 || low < 0) { + byte = hexits_value(arg, 2, &ok); + if (!ok) { ovs_fatal(0, "bad hex digit in `note' argument"); } - - byte = high * 16 + low; ofpbuf_put(b, &byte, 1); + + arg += 2; } len = b->size - start_ofs; diff --git a/lib/sha1.c b/lib/sha1.c index 205b82fe0..3b16622df 100644 --- a/lib/sha1.c +++ b/lib/sha1.c @@ -1,7 +1,7 @@ /* * This file is from the Apache Portable Runtime Library. * The full upstream copyright and license statement is included below. - * Modifications copyright (c) 2009 Nicira Networks. + * Modifications copyright (c) 2009, 2010 Nicira Networks. */ /* Licensed to the Apache Software Foundation (ASF) under one or more @@ -301,10 +301,12 @@ sha1_from_hex(uint8_t digest[SHA1_DIGEST_SIZE], const char *hex) int i; for (i = 0; i < SHA1_DIGEST_SIZE; i++) { - if (!isxdigit(hex[0]) || !isxdigit(hex[1])) { + bool ok; + + digest[i] = hexits_value(hex, 2, &ok); + if (!ok) { return false; } - digest[i] = (hexit_value(hex[0]) << 4) | hexit_value(hex[1]); hex += 2; } return true; diff --git a/lib/util.c b/lib/util.c index 12403cbbc..4f1b9f758 100644 --- a/lib/util.c +++ b/lib/util.c @@ -364,6 +364,33 @@ hexit_value(int c) } } +/* Returns the integer value of the 'n' hexadecimal digits starting at 's', or + * UINT_MAX if one of those "digits" is not really a hex digit. If 'ok' is + * nonnull, '*ok' is set to true if the conversion succeeds or to false if a + * non-hex digit is detected. */ +unsigned int +hexits_value(const char *s, size_t n, bool *ok) +{ + unsigned int value; + size_t i; + + value = 0; + for (i = 0; i < n; i++) { + int hexit = hexit_value(s[i]); + if (hexit < 0) { + if (ok) { + *ok = false; + } + return UINT_MAX; + } + value = (value << 4) + hexit; + } + if (ok) { + *ok = true; + } + return value; +} + /* Returns the current working directory as a malloc()'d string, or a null * pointer if the current working directory cannot be determined. */ char * diff --git a/lib/util.h b/lib/util.h index 6bc174040..703b93cf4 100644 --- a/lib/util.h +++ b/lib/util.h @@ -132,6 +132,7 @@ bool str_to_ullong(const char *, int base, unsigned long long *); bool str_to_double(const char *, double *); int hexit_value(int c); +unsigned int hexits_value(const char *s, size_t n, bool *ok); char *get_cwd(void); char *dir_name(const char *file_name); diff --git a/lib/uuid.c b/lib/uuid.c index 2aac4c720..e25902423 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -156,23 +156,43 @@ uuid_from_string(struct uuid *uuid, const char *s) bool uuid_from_string_prefix(struct uuid *uuid, const char *s) { - static const char template[] = "00000000-1111-1111-2222-222233333333"; - const char *t; + /* 0 1 2 3 */ + /* 012345678901234567890123456789012345 */ + /* ------------------------------------ */ + /* 00000000-1111-1111-2222-222233333333 */ - uuid_zero(uuid); - for (t = template; ; t++, s++) { - if (*t >= '0' && *t <= '3') { - uint32_t *part = &uuid->parts[*t - '0']; - if (!isxdigit(*s)) { - goto error; - } - *part = (*part << 4) + hexit_value(*s); - } else if (*t == 0) { - return true; - } else if (*t != *s) { - goto error; - } + bool ok; + + uuid->parts[0] = hexits_value(s, 8, &ok); + if (!ok || s[8] != '-') { + goto error; + } + + uuid->parts[1] = hexits_value(s + 9, 4, &ok) << 16; + if (!ok || s[13] != '-') { + goto error; + } + + uuid->parts[1] += hexits_value(s + 14, 4, &ok); + if (!ok || s[18] != '-') { + goto error; + } + + uuid->parts[2] = hexits_value(s + 19, 4, &ok) << 16; + if (!ok || s[23] != '-') { + goto error; + } + + uuid->parts[2] += hexits_value(s + 24, 4, &ok); + if (!ok) { + goto error; + } + + uuid->parts[3] = hexits_value(s + 28, 8, &ok); + if (!ok) { + goto error; } + return true; error: uuid_zero(uuid); diff --git a/tests/test-aes128.c b/tests/test-aes128.c index 8a6c28cde..e7e990c69 100644 --- a/tests/test-aes128.c +++ b/tests/test-aes128.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Nicira Networks. + * Copyright (c) 2009, 2010 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,13 +28,12 @@ hex_to_uint8(const char *input, uint8_t *output, size_t n) goto error; } for (i = 0; i < n; i++) { - unsigned char hi = input[i * 2]; - unsigned char lo = input[i * 2 + 1]; + bool ok; - if (!isxdigit(hi) || !isxdigit(lo)) { + output[i] = hexits_value(&input[i * 2], 2, &ok); + if (!ok) { goto error; } - output[i] = (hexit_value(hi) << 4) + hexit_value(lo); } return; -- 2.43.0