From 4aae004629bfb367aa37a6ad6a722f44cc0e9ddf Mon Sep 17 00:00:00 2001 From: Chris Hofstaedtler Date: Tue, 29 Nov 2022 12:18:06 +0100 Subject: [PATCH] autolink: avoid out-of-bounds read in validate_protocol If validate_protocol runs with the "protocol:..." string starting exactly at the underlying memory buffer used in postprocess_text, prev_char will point to a byte _before_ that memory buffer, and the check will essentially be random. Apparently this works "fine" on little endian architectures, but on big-endian (like s390x, hppa, ppc, ppc64, ...) this fails. And for good reason! Avoid the prev_char check by forwarding the underlying buffer as "start" into validate_protocol. Fixes build failure in Debian on s390x. Debian bug: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1023020 --- extensions/autolink.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/extensions/autolink.c b/extensions/autolink.c index 838374c29..8d5a2ea7e 100644 --- a/extensions/autolink.c +++ b/extensions/autolink.c @@ -269,7 +269,7 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser, // inline was finished in inlines.c. } -static bool validate_protocol(char protocol[], uint8_t *data, int rewind) { +static bool validate_protocol(char protocol[], uint8_t *data, int rewind, uint8_t* start) { size_t len = strlen(protocol); // Check that the protocol matches @@ -279,6 +279,9 @@ static bool validate_protocol(char protocol[], uint8_t *data, int rewind) { } } + if (start >= data - rewind - len) + return true; // start of text, skip prev_char check + char prev_char = data[-rewind - len - 1]; // Make sure the character before the protocol is non-alphanumeric @@ -323,12 +326,12 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset, continue; if (strchr(":", c) != NULL) { - if (validate_protocol("mailto:", data, rewind)) { + if (validate_protocol("mailto:", data, rewind, text->as.literal.data)) { auto_mailto = false; continue; } - if (validate_protocol("xmpp:", data, rewind)) { + if (validate_protocol("xmpp:", data, rewind, text->as.literal.data)) { auto_mailto = false; is_xmpp = true; continue;