aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_uuid.c56
-rw-r--r--sys/sys/uuid.h15
2 files changed, 53 insertions, 18 deletions
diff --git a/sys/kern/kern_uuid.c b/sys/kern/kern_uuid.c
index ea0877a0cde0..984a2b8cd6ac 100644
--- a/sys/kern/kern_uuid.c
+++ b/sys/kern/kern_uuid.c
@@ -382,19 +382,16 @@ be_uuid_dec(void const *buf, struct uuid *uuid)
}
int
-parse_uuid(const char *str, struct uuid *uuid)
+validate_uuid(const char *str, size_t size, struct uuid *uuid)
{
u_int c[11];
int n;
- /* An empty string represents a nil UUID. */
- if (*str == '\0') {
- bzero(uuid, sizeof(*uuid));
- return (0);
- }
+ if (size == 0 || *str == '\0')
+ return (EINVAL);
/* The UUID string representation has a fixed length. */
- if (strlen(str) != 36)
+ if (size != 36)
return (EINVAL);
/*
@@ -406,25 +403,48 @@ parse_uuid(const char *str, struct uuid *uuid)
if (str[8] != '-')
return (EINVAL);
+ /* Now check the format. */
n = sscanf(str, "%8x-%4x-%4x-%2x%2x-%2x%2x%2x%2x%2x%2x", c + 0, c + 1,
c + 2, c + 3, c + 4, c + 5, c + 6, c + 7, c + 8, c + 9, c + 10);
/* Make sure we have all conversions. */
if (n != 11)
return (EINVAL);
- /* Successful scan. Build the UUID. */
- uuid->time_low = c[0];
- uuid->time_mid = c[1];
- uuid->time_hi_and_version = c[2];
- uuid->clock_seq_hi_and_reserved = c[3];
- uuid->clock_seq_low = c[4];
- for (n = 0; n < 6; n++)
- uuid->node[n] = c[n + 5];
+ /* Successful scan. Build the UUID if requested. */
+ if (uuid != NULL) {
+ uuid->time_low = c[0];
+ uuid->time_mid = c[1];
+ uuid->time_hi_and_version = c[2];
+ uuid->clock_seq_hi_and_reserved = c[3];
+ uuid->clock_seq_low = c[4];
+ for (n = 0; n < 6; n++)
+ uuid->node[n] = c[n + 5];
+ }
+
+ return (0);
+}
+
+int
+parse_uuid(const char *str, struct uuid *uuid)
+{
+ unsigned int clock_seq;
+ int ret;
+
+ /* An empty string represents a nil UUID. */
+ if (*str == '\0') {
+ bzero(uuid, sizeof(*uuid));
+ return (0);
+ }
+
+ ret = validate_uuid(str, strlen(str), uuid);
+ if (ret != 0)
+ return (ret);
/* Check semantics... */
- return (((c[3] & 0x80) != 0x00 && /* variant 0? */
- (c[3] & 0xc0) != 0x80 && /* variant 1? */
- (c[3] & 0xe0) != 0xc0) ? EINVAL : 0); /* variant 2? */
+ clock_seq = uuid->clock_seq_hi_and_reserved;
+ return (((clock_seq & 0x80) != 0x00 && /* variant 0? */
+ (clock_seq & 0xc0) != 0x80 && /* variant 1? */
+ (clock_seq & 0xe0) != 0xc0) ? EINVAL : 0); /* variant 2? */
}
int
diff --git a/sys/sys/uuid.h b/sys/sys/uuid.h
index e60af2180f14..9f0ea3d70fd4 100644
--- a/sys/sys/uuid.h
+++ b/sys/sys/uuid.h
@@ -66,6 +66,21 @@ int uuid_ether_del(const uint8_t *);
int snprintf_uuid(char *, size_t, struct uuid *);
int printf_uuid(struct uuid *);
int sbuf_printf_uuid(struct sbuf *, struct uuid *);
+
+/*
+ * There are a few key differences between validate_uuid and parse_uuid:
+ *
+ * - The struct uuid * parameter to validate_uuid is optional, so the caller
+ * can simply validate UUID format without doing anything with the result.
+ * - validate_uuid will not pass an empty string as a valid UUID, as it doesn't
+ * strictly meet the formatting requirements. parse_uuid will accept an
+ * empty string and zero out the uuid struct accordingly.
+ * - parse_uuid does additional semantic checks on clock_seq_hi_and_reserved
+ * that validate_uuid will not do.
+ *
+ * validate_uuid is intended to strictly check that it's a well-formed uuid.
+ */
+int validate_uuid(const char *, size_t, struct uuid *);
int parse_uuid(const char *, struct uuid *);
int uuidcmp(const struct uuid *, const struct uuid *);