From: "brian m. carlson" <sandals@crustytoothpaste.net>
To: git@vger.kernel.org
Cc: gitster@pobox.com
Subject: [PATCH v2 1/2] commit: reject invalid UTF-8 codepoints
Date: Thu, 4 Jul 2013 17:19:43 +0000 [thread overview]
Message-ID: <20130704171943.GA267700@vauxhall.crustytoothpaste.net> (raw)
In-Reply-To: <cover.1372957719.git.sandals@crustytoothpaste.net>
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@crustytoothpaste.net>
---
commit.c | 27 ++++++++++++++++++++++-----
t/t3900-i18n-commit.sh | 12 ++++++++++++
2 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/commit.c b/commit.c
index 888e02a..2264106 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,40 @@ 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. Longer sequences result in
+ * codepoints beyond U+10FFFF, which are guaranteed never to exist.
+ */
+ 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 */
+ /* No codepoints can ever be allocated beyond U+10FFFF. */
+ if (codepoint > 0x10ffff)
+ return bad_offset;
+ /* Surrogates are only for UTF-16 and cannot be encoded in UTF-8. */
+ if ((codepoint & 0x1ff800) == 0xd800)
+ return bad_offset;
+ /* U+FFFE and U+FFFF are guaranteed non-characters. */
+ if ((codepoint & 0x1ffffe) == 0xfffe)
+ return bad_offset;
}
return -1;
}
@@ -1292,8 +1309,8 @@ static int find_invalid_utf8(const char *buf, int len)
* If it isn't, it assumes any non-utf8 characters are Latin1,
* and does the conversion.
*
- * Fixme: we should probably also disallow overlong forms and
- * invalid characters. But we don't do that currently.
+ * Fixme: we should probably also disallow overlong forms.
+ * But we don't do that currently.
*/
static int verify_utf8(struct strbuf *buf)
{
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 37ddabb..ee8ba6c 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -39,6 +39,18 @@ 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' '
+ test_when_finished "rm -f $HOME/stderr $HOME/invalid" &&
+ rm -f "$HOME/stderr" &&
+ echo "UTF-8 characters" >F &&
+ printf "Commit message\n\nInvalid surrogate:\355\240\200\n" \
+ >"$HOME/invalid" &&
+ git commit -a -F "$HOME/invalid" \
+ 2>"$HOME"/stderr &&
+ grep "did not conform" "$HOME"/stderr
+'
+
+rm -f "$HOME/stderr"
for H in ISO8859-1 eucJP ISO-2022-JP
do
--
1.8.3.1
next prev parent reply other threads:[~2013-07-04 17:27 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-04 17:17 [PATCH v2 0/2] commit: improve UTF-8 validation brian m. carlson
2013-07-04 17:19 ` brian m. carlson [this message]
2013-07-04 19:58 ` [PATCH v2 1/2] commit: reject invalid UTF-8 codepoints Torsten Bögershausen
2013-07-04 20:39 ` brian m. carlson
2013-07-05 12:51 ` Peter Krefting
2013-07-08 19:36 ` Junio C Hamano
2013-07-09 11:16 ` [PATCH] commit: reject non-characters Peter Krefting
2013-08-05 12:48 ` Peter Krefting
2013-08-05 16:54 ` Junio C Hamano
2013-08-06 7:03 ` Peter Krefting
2013-07-04 17:20 ` [PATCH v2 2/2] commit: reject overlong UTF-8 sequences brian m. carlson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130704171943.GA267700@vauxhall.crustytoothpaste.net \
--to=sandals@crustytoothpaste.net \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).