122 lines
4.5 KiB
Diff
122 lines
4.5 KiB
Diff
From 304a50adff6480ede46b68f7545baab542cbfb46 Mon Sep 17 00:00:00 2001
|
|
From: Patrick Steinhardt <ps@pks.im>
|
|
Date: Thu, 1 Dec 2022 15:47:23 +0100
|
|
Subject: [PATCH] pretty: restrict input lengths for padding and wrapping
|
|
formats
|
|
|
|
Both the padding and wrapping formatting directives allow the caller to
|
|
specify an integer that ultimately leads to us adding this many chars to
|
|
the result buffer. As a consequence, it is trivial to e.g. allocate 2GB
|
|
of RAM via a single formatting directive and cause resource exhaustion
|
|
on the machine executing this logic. Furthermore, it is debatable
|
|
whether there are any sane usecases that require the user to pad data to
|
|
2GB boundaries or to indent wrapped data by 2GB.
|
|
|
|
Restrict the input sizes to 16 kilobytes at a maximum to limit the
|
|
amount of bytes that can be requested by the user. This is not meant
|
|
as a fix because there are ways to trivially amplify the amount of
|
|
data we generate via formatting directives; the real protection is
|
|
achieved by the changes in previous steps to catch and avoid integer
|
|
wraparound that causes us to under-allocate and access beyond the
|
|
end of allocated memory reagions. But having such a limit
|
|
significantly helps fuzzing the pretty format, because the fuzzer is
|
|
otherwise quite fast to run out-of-memory as it discovers these
|
|
formatters.
|
|
|
|
Signed-off-by: Patrick Steinhardt <ps@pks.im>
|
|
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
|
---
|
|
pretty.c | 26 ++++++++++++++++++++++++++
|
|
t/t4205-log-pretty-formats.sh | 24 +++++++++++++++---------
|
|
2 files changed, 41 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/pretty.c b/pretty.c
|
|
index aae6e792bc..e2285572c4 100644
|
|
--- a/pretty.c
|
|
+++ b/pretty.c
|
|
@@ -13,6 +13,13 @@
|
|
#include "trailer.h"
|
|
#include "run-command.h"
|
|
|
|
+/*
|
|
+ * The limit for formatting directives, which enable the caller to append
|
|
+ * arbitrarily many bytes to the formatted buffer. This includes padding
|
|
+ * and wrapping formatters.
|
|
+ */
|
|
+#define FORMATTING_LIMIT (16 * 1024)
|
|
+
|
|
static char *user_format;
|
|
static struct cmt_fmt_map {
|
|
const char *name;
|
|
@@ -1046,6 +1053,15 @@ static size_t parse_padding_placeholder(const char *placeholder,
|
|
if (!*end || end == start)
|
|
return 0;
|
|
width = strtol(start, &next, 10);
|
|
+
|
|
+ /*
|
|
+ * We need to limit the amount of padding, or otherwise this
|
|
+ * would allow the user to pad the buffer by arbitrarily many
|
|
+ * bytes and thus cause resource exhaustion.
|
|
+ */
|
|
+ if (width < -FORMATTING_LIMIT || width > FORMATTING_LIMIT)
|
|
+ return 0;
|
|
+
|
|
if (next == start || width == 0)
|
|
return 0;
|
|
if (width < 0) {
|
|
@@ -1205,6 +1221,16 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
|
|
if (*next != ')')
|
|
return 0;
|
|
}
|
|
+
|
|
+ /*
|
|
+ * We need to limit the format here as it allows the
|
|
+ * user to prepend arbitrarily many bytes to the buffer
|
|
+ * when rewrapping.
|
|
+ */
|
|
+ if (width > FORMATTING_LIMIT ||
|
|
+ indent1 > FORMATTING_LIMIT ||
|
|
+ indent2 > FORMATTING_LIMIT)
|
|
+ return 0;
|
|
rewrap_message_tail(sb, c, width, indent1, indent2);
|
|
return end - placeholder + 1;
|
|
} else
|
|
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
|
|
index 5c5b56596e..84c61dfc48 100755
|
|
--- a/t/t4205-log-pretty-formats.sh
|
|
+++ b/t/t4205-log-pretty-formats.sh
|
|
@@ -888,15 +888,21 @@ test_expect_success 'log --pretty with magical wrapping directives' '
|
|
'
|
|
|
|
test_expect_success SIZE_T_IS_64BIT 'log --pretty with overflowing wrapping directive' '
|
|
- cat >expect <<-EOF &&
|
|
- fatal: number too large to represent as int on this platform: 2147483649
|
|
- EOF
|
|
- test_must_fail git log -1 --pretty="format:%w(2147483649,1,1)%d" 2>error &&
|
|
- test_cmp expect error &&
|
|
- test_must_fail git log -1 --pretty="format:%w(1,2147483649,1)%d" 2>error &&
|
|
- test_cmp expect error &&
|
|
- test_must_fail git log -1 --pretty="format:%w(1,1,2147483649)%d" 2>error &&
|
|
- test_cmp expect error
|
|
+ printf "%%w(2147483649,1,1)0" >expect &&
|
|
+ git log -1 --pretty="format:%w(2147483649,1,1)%x30" >actual &&
|
|
+ test_cmp expect actual &&
|
|
+ printf "%%w(1,2147483649,1)0" >expect &&
|
|
+ git log -1 --pretty="format:%w(1,2147483649,1)%x30" >actual &&
|
|
+ test_cmp expect actual &&
|
|
+ printf "%%w(1,1,2147483649)0" >expect &&
|
|
+ git log -1 --pretty="format:%w(1,1,2147483649)%x30" >actual &&
|
|
+ test_cmp expect actual
|
|
+'
|
|
+
|
|
+test_expect_success SIZE_T_IS_64BIT 'log --pretty with overflowing padding directive' '
|
|
+ printf "%%<(2147483649)0" >expect &&
|
|
+ git log -1 --pretty="format:%<(2147483649)%x30" >actual &&
|
|
+ test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'log --pretty with padding and preceding control chars' '
|
|
--
|
|
2.27.0
|
|
|