From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp47.i.mail.ru (smtp47.i.mail.ru [94.100.177.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 21EA04696C5 for ; Sat, 4 Apr 2020 02:03:10 +0300 (MSK) From: Serge Petrenko Date: Sat, 4 Apr 2020 02:02:50 +0300 Message-Id: <9042734e4ddc49d2e8903b346b84d699d1e2c46b.1585954493.git.sergepetrenko@tarantool.org> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH 2/4] uuid: expose additional from_string constructors List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: v.shpilevoy@tarantool.org Cc: tarantool-patches@dev.tarantool.org tt_uuid_from_string() checks string length via strlen to determine whether the string is valid. When a string is decoded from arbitrary msgpack data, it may not be null-terminated, so strlen() will return incorrect results. When a string is decoded from msgpack, its length is returned from the decoder, so add tt_uuid_from_lstring(), which accepts string length and validates it. Allow tt_uuid_from_lstring() construct uuids from both 'normal' 36-byte strings, like '88ebbb9a-8c18-480f-bd04-dd5345f1573c', and 32-byte stripped strings, like '88ebbb9a8c18480fbd04dd5345f1573c'. Add a function tt_uuid_validate(), which checks that uuid conforms to one of the variants. Prerequisite #4268 --- src/lib/uuid/tt_uuid.c | 9 +++++++ src/lib/uuid/tt_uuid.h | 53 ++++++++++++++++++++++++++++++++---------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/lib/uuid/tt_uuid.c b/src/lib/uuid/tt_uuid.c index 1bd2e2cfe..94a0b15bb 100644 --- a/src/lib/uuid/tt_uuid.c +++ b/src/lib/uuid/tt_uuid.c @@ -65,6 +65,15 @@ tt_uuid_create(struct tt_uuid *uu) } #endif +extern inline int +tt_uuid_validate(struct tt_uuid *uu); + +extern inline int +tt_uuid_from_fmt_string(const char *in, struct tt_uuid *uu, const char *fmt); + +extern inline int +tt_uuid_from_lstring(const char *in, uint32_t len, struct tt_uuid *uu); + extern inline int tt_uuid_from_string(const char *in, struct tt_uuid *uu); diff --git a/src/lib/uuid/tt_uuid.h b/src/lib/uuid/tt_uuid.h index 48cd68e69..8f293a1e0 100644 --- a/src/lib/uuid/tt_uuid.h +++ b/src/lib/uuid/tt_uuid.h @@ -41,7 +41,7 @@ extern "C" { #endif -enum { UUID_LEN = 16, UUID_STR_LEN = 36 }; +enum { UUID_LEN = 16, UUID_STR_PLAIN_LEN = 32, UUID_STR_LEN = 36 }; /** * \brief UUID structure struct @@ -62,6 +62,28 @@ struct tt_uuid { void tt_uuid_create(struct tt_uuid *uu); +inline int +tt_uuid_validate(struct tt_uuid *uu) +{ + /* Check variant (NCS, RFC4122, MSFT) */ + uint8_t n = uu->clock_seq_hi_and_reserved; + if ((n & 0x80) != 0x00 && (n & 0xc0) != 0x80 && (n & 0xe0) != 0xc0) + return 1; + return 0; +} + +inline int +tt_uuid_from_fmt_string(const char *in, struct tt_uuid *uu, + const char *fmt) +{ + if (sscanf(in, fmt, &uu->time_low, &uu->time_mid, + &uu->time_hi_and_version, &uu->clock_seq_hi_and_reserved, + &uu->clock_seq_low, &uu->node[0], &uu->node[1], &uu->node[2], + &uu->node[3], &uu->node[4], &uu->node[5]) != 11) + return 1; + return tt_uuid_validate(uu); +} + /** * \brief Parse UUID from string. * \param in string @@ -71,19 +93,26 @@ tt_uuid_create(struct tt_uuid *uu); inline int tt_uuid_from_string(const char *in, struct tt_uuid *uu) { - if (strlen(in) != UUID_STR_LEN || - sscanf(in, "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", - &uu->time_low, &uu->time_mid, &uu->time_hi_and_version, - &uu->clock_seq_hi_and_reserved, &uu->clock_seq_low, - &uu->node[0], &uu->node[1], &uu->node[2], &uu->node[3], - &uu->node[4], &uu->node[5]) != 11) + if (strlen(in) != UUID_STR_LEN) return 1; + return tt_uuid_from_fmt_string(in, uu, + "%8x-%4hx-%4hx-%2hhx%2hhx-" + "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"); +} - /* Check variant (NCS, RFC4122, MSFT) */ - uint8_t n = uu->clock_seq_hi_and_reserved; - if ((n & 0x80) != 0x00 && (n & 0xc0) != 0x80 && (n & 0xe0) != 0xc0) - return 1; - return 0; +inline int +tt_uuid_from_lstring(const char *in, uint32_t len, struct tt_uuid *uu) +{ + if (len == UUID_STR_PLAIN_LEN) { + return tt_uuid_from_fmt_string(in, uu, + "%8x%4hx%4hx%2hhx%2hhx%2hhx%2hhx" + "%2hhx%2hhx%2hhx%2hhx"); + } else if (len == UUID_STR_LEN) { + return tt_uuid_from_fmt_string(in, uu, + "%8x-%4hx-%4hx-%2hhx%2hhx-" + "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx"); + } + return 1; } /** -- 2.21.1 (Apple Git-122.3)