The commit code accepts pseudo-UTF-8 sequences that encode a character with more bytes than necessary. Reject such sequences, since they are not valid UTF-8. Signed-off-by: brian m. carlson <sandals@xxxxxxxxxxxxxxxxxxxx> --- commit.c | 14 ++++++++++++-- t/t3900-i18n-commit.sh | 8 ++++++++ t/t3900/UTF-8-overlong.txt | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 t/t3900/UTF-8-overlong.txt diff --git a/commit.c b/commit.c index 2280413..e57fec6 100644 --- a/commit.c +++ b/commit.c @@ -1240,11 +1240,15 @@ int commit_tree(const struct strbuf *msg, unsigned char *tree, static int find_invalid_utf8(const char *buf, int len) { int offset = 0; + static const unsigned int max_codepoint[] = { + 0x7f, 0x7ff, 0xffff, 0x1fffff + }; while (len) { unsigned char c = *buf++; int bytes, bad_offset; unsigned int codepoint; + unsigned int min_val, max_val; len--; offset++; @@ -1273,8 +1277,12 @@ static int find_invalid_utf8(const char *buf, int len) if (len < bytes) return bad_offset; - /* Place the encoded bits at the bottom of the value. */ + /* Place the encoded bits at the bottom of the value and compute the + * valid range. + */ codepoint = (c & 0x7f) >> bytes; + min_val = max_codepoint[bytes-1] + 1; + max_val = max_codepoint[bytes]; offset += bytes; len -= bytes; @@ -1287,13 +1295,15 @@ static int find_invalid_utf8(const char *buf, int len) return bad_offset; } while (--bytes); - /* Check the value here */ + /* Check the value and length here */ if (codepoint >= 0xd800 && codepoint <= 0xdfff) return bad_offset; if (codepoint > 0x10ffff) return bad_offset; if ((codepoint & 0x1ffffe) == 0xfffe) return bad_offset; + if (codepoint < min_val || codepoint > max_val) + return bad_offset; } return -1; } diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index 16ed707..de0fcef 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -47,6 +47,14 @@ test_expect_success 'UTF-8 invalid characters refused' ' grep "did not conform" "$HOME"/stderr ' +test_expect_success 'UTF-8 overlong sequences rejected' ' + rm -f "$HOME/stderr" && + echo "UTF-8 overlong" >F && + git commit -a -F "$TEST_DIRECTORY"/t3900/UTF-8-overlong.txt \ + 2>"$HOME"/stderr && + grep "did not conform" "$HOME"/stderr +' + rm -f "$HOME/stderr" for H in ISO8859-1 eucJP ISO-2022-JP diff --git a/t/t3900/UTF-8-overlong.txt b/t/t3900/UTF-8-overlong.txt new file mode 100644 index 0000000..fa157e9 --- /dev/null +++ b/t/t3900/UTF-8-overlong.txt @@ -0,0 +1,3 @@ +???ommit message + +This is not a space:?? -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html