The commit code already contains code for validating UTF-8, but it does not check for invalid values, such as guaranteed non-characters and surrogates. Fix this by explicitly checking for and rejecting such characters. Signed-off-by: brian m. carlson <sandals@xxxxxxxxxxxxxxxxxxxx> --- commit.c | 18 +++++++++++++++--- t/t3900-i18n-commit.sh | 9 +++++++++ t/t3900/UTF-8-invalid.txt | 3 +++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 t/t3900/UTF-8-invalid.txt diff --git a/commit.c b/commit.c index 888e02a..2280413 100644 --- a/commit.c +++ b/commit.c @@ -1244,6 +1244,7 @@ static int find_invalid_utf8(const char *buf, int len) while (len) { unsigned char c = *buf++; int bytes, bad_offset; + unsigned int codepoint; len--; offset++; @@ -1264,24 +1265,35 @@ static int find_invalid_utf8(const char *buf, int len) bytes++; } - /* Must be between 1 and 5 more bytes */ - if (bytes < 1 || bytes > 5) + /* Must be between 1 and 3 more bytes */ + if (bytes < 1 || bytes > 3) return bad_offset; /* Do we *have* that many bytes? */ if (len < bytes) return bad_offset; + /* Place the encoded bits at the bottom of the value. */ + codepoint = (c & 0x7f) >> bytes; + offset += bytes; len -= bytes; /* And verify that they are good continuation bytes */ do { + codepoint <<= 6; + codepoint |= *buf & 0x3f; if ((*buf++ & 0xc0) != 0x80) return bad_offset; } while (--bytes); - /* We could/should check the value and length here too */ + /* Check the value here */ + if (codepoint >= 0xd800 && codepoint <= 0xdfff) + return bad_offset; + if (codepoint > 0x10ffff) + return bad_offset; + if ((codepoint & 0x1ffffe) == 0xfffe) + return bad_offset; } return -1; } diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index 37ddabb..16ed707 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -39,6 +39,15 @@ test_expect_failure 'UTF-16 refused because of NULs' ' git commit -a -F "$TEST_DIRECTORY"/t3900/UTF-16.txt ' +test_expect_success 'UTF-8 invalid characters refused' ' + rm -f "$HOME/stderr" && + echo "UTF-8 characters" >F && + git commit -a -F "$TEST_DIRECTORY"/t3900/UTF-8-invalid.txt \ + 2>"$HOME"/stderr && + grep "did not conform" "$HOME"/stderr +' + +rm -f "$HOME/stderr" for H in ISO8859-1 eucJP ISO-2022-JP do diff --git a/t/t3900/UTF-8-invalid.txt b/t/t3900/UTF-8-invalid.txt new file mode 100644 index 0000000..343684d --- /dev/null +++ b/t/t3900/UTF-8-invalid.txt @@ -0,0 +1,3 @@ +Commit message + +Invalid surrogate:??? -- 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