Skip to content

Commit 304a50a

Browse files
pks-tgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f930a23 commit 304a50a

File tree

2 files changed

+41
-9
lines changed

2 files changed

+41
-9
lines changed

pretty.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@
1313
#include "gpg-interface.h"
1414
#include "trailer.h"
1515

16+
/*
17+
* The limit for formatting directives, which enable the caller to append
18+
* arbitrarily many bytes to the formatted buffer. This includes padding
19+
* and wrapping formatters.
20+
*/
21+
#define FORMATTING_LIMIT (16 * 1024)
22+
1623
static char *user_format;
1724
static struct cmt_fmt_map {
1825
const char *name;
@@ -1046,6 +1053,15 @@ static size_t parse_padding_placeholder(const char *placeholder,
10461053
if (!*end || end == start)
10471054
return 0;
10481055
width = strtol(start, &next, 10);
1056+
1057+
/*
1058+
* We need to limit the amount of padding, or otherwise this
1059+
* would allow the user to pad the buffer by arbitrarily many
1060+
* bytes and thus cause resource exhaustion.
1061+
*/
1062+
if (width < -FORMATTING_LIMIT || width > FORMATTING_LIMIT)
1063+
return 0;
1064+
10491065
if (next == start || width == 0)
10501066
return 0;
10511067
if (width < 0) {
@@ -1205,6 +1221,16 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
12051221
if (*next != ')')
12061222
return 0;
12071223
}
1224+
1225+
/*
1226+
* We need to limit the format here as it allows the
1227+
* user to prepend arbitrarily many bytes to the buffer
1228+
* when rewrapping.
1229+
*/
1230+
if (width > FORMATTING_LIMIT ||
1231+
indent1 > FORMATTING_LIMIT ||
1232+
indent2 > FORMATTING_LIMIT)
1233+
return 0;
12081234
rewrap_message_tail(sb, c, width, indent1, indent2);
12091235
return end - placeholder + 1;
12101236
} else

t/t4205-log-pretty-formats.sh

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -888,15 +888,21 @@ test_expect_success 'log --pretty with magical wrapping directives' '
888888
'
889889

890890
test_expect_success SIZE_T_IS_64BIT 'log --pretty with overflowing wrapping directive' '
891-
cat >expect <<-EOF &&
892-
fatal: number too large to represent as int on this platform: 2147483649
893-
EOF
894-
test_must_fail git log -1 --pretty="format:%w(2147483649,1,1)%d" 2>error &&
895-
test_cmp expect error &&
896-
test_must_fail git log -1 --pretty="format:%w(1,2147483649,1)%d" 2>error &&
897-
test_cmp expect error &&
898-
test_must_fail git log -1 --pretty="format:%w(1,1,2147483649)%d" 2>error &&
899-
test_cmp expect error
891+
printf "%%w(2147483649,1,1)0" >expect &&
892+
git log -1 --pretty="format:%w(2147483649,1,1)%x30" >actual &&
893+
test_cmp expect actual &&
894+
printf "%%w(1,2147483649,1)0" >expect &&
895+
git log -1 --pretty="format:%w(1,2147483649,1)%x30" >actual &&
896+
test_cmp expect actual &&
897+
printf "%%w(1,1,2147483649)0" >expect &&
898+
git log -1 --pretty="format:%w(1,1,2147483649)%x30" >actual &&
899+
test_cmp expect actual
900+
'
901+
902+
test_expect_success SIZE_T_IS_64BIT 'log --pretty with overflowing padding directive' '
903+
printf "%%<(2147483649)0" >expect &&
904+
git log -1 --pretty="format:%<(2147483649)%x30" >actual &&
905+
test_cmp expect actual
900906
'
901907

902908
test_expect_success 'log --pretty with padding and preceding control chars' '

0 commit comments

Comments
 (0)