diff options
author | Florian Westphal <fw@strlen.de> | 2023-12-13 17:37:11 +0100 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2023-12-13 18:11:20 +0100 |
commit | 7008b1200fb4988b7cd7ee1c5399cae071688d50 (patch) | |
tree | 36e8e52f1a5bb8ceb1afa030dad3834757686e21 /src | |
parent | c0194279d356f942e81555262e41264af7659a1f (diff) |
meta: fix tc classid parsing out-of-bounds access
AddressSanitizer: heap-buffer-overflow on address 0x6020000003af ...
#0 0x7f9a83cbb402 in tchandle_type_parse src/meta.c:89
#1 0x7f9a83c6753f in symbol_parse src/datatype.c:138
strlen() - 1 can underflow if length was 0.
Simplify the function, there is no need to duplicate the string
while scanning it.
Expect the first strtol to stop at ':', scan for the minor number next.
The second scan is required to stop at '\0'.
Fixes: 6f2eb8548e0d ("src: meta priority support using tc classid")
Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/meta.c | 29 |
1 files changed, 9 insertions, 20 deletions
@@ -62,50 +62,39 @@ static struct error_record *tchandle_type_parse(struct parse_ctx *ctx, struct expr **res) { uint32_t handle; - char *str = NULL; if (strcmp(sym->identifier, "root") == 0) handle = TC_H_ROOT; else if (strcmp(sym->identifier, "none") == 0) handle = TC_H_UNSPEC; else if (strchr(sym->identifier, ':')) { + char *colon, *end; uint32_t tmp; - char *colon; - - str = xstrdup(sym->identifier); - - colon = strchr(str, ':'); - if (!colon) - goto err; - - *colon = '\0'; errno = 0; - tmp = strtoull(str, NULL, 16); - if (errno != 0) + tmp = strtoul(sym->identifier, &colon, 16); + if (errno != 0 || sym->identifier == colon) goto err; - handle = (tmp << 16); - if (str[strlen(str) - 1] == ':') - goto out; + if (*colon != ':') + goto err; + handle = tmp << 16; errno = 0; - tmp = strtoull(colon + 1, NULL, 16); - if (errno != 0) + tmp = strtoul(colon + 1, &end, 16); + if (errno != 0 || *end) goto err; handle |= tmp; } else { handle = strtoull(sym->identifier, NULL, 0); } -out: - free(str); + *res = constant_expr_alloc(&sym->location, sym->dtype, BYTEORDER_HOST_ENDIAN, sizeof(handle) * BITS_PER_BYTE, &handle); return NULL; err: - free(str); return error(&sym->location, "Could not parse %s", sym->dtype->desc); } |