Skip to content

Commit 2c9b9a9

Browse files
Byroncodex
andcommitted
review
I didn't try to fix all the issues with this, let's just make it a little bit better hoping the code won't be around much longer. <!-- agent --> # Known limitations Commit.encoding still conflates the declared encoding with the codec used for best-effort decoding. Unsupported or malformed declarations leave the default encoding—or an earlier accepted declaration—in place, so the resulting attribute does not faithfully represent the commit’s original metadata. The rejected header bytes appear in the diagnostic but are not retained on the object. Fallback decoding with "replace" can irreversibly alter identity and message content. Reserializing such a commit can therefore change both its encoding declaration and its content; this change does not provide lossless round-tripping. Codec validation also checks only that Python accepts the codec, not that it can decode the actual commit content. Assisted-by: GPT 6.1 Sol Co-authored-by: GPT 6.1 Sol <codex@openai.com>
1 parent b145459 commit 2c9b9a9

2 files changed

Lines changed: 26 additions & 4 deletions

File tree

‎git/objects/commit.py‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -897,14 +897,16 @@ def _deserialize(self, stream: BytesIO) -> "Commit":
897897
buf = enc.strip()
898898
while buf:
899899
if buf[0:9] == b"encoding ":
900-
encoding = buf[buf.find(b" ") + 1 :].decode(self.encoding, "ignore")
900+
raw_encoding = buf[9:]
901901
try:
902+
# Codec names are ASCII, independent of the content encoding.
903+
encoding = raw_encoding.decode("ascii")
902904
# Probe one byte: decoding b"" skips the codec lookup entirely.
903905
b" ".decode(encoding, "replace")
904906
except (LookupError, ValueError):
905-
# The encoding is not a text encoding Python knows; keep the
906-
# default so the identity and message lines still decode below.
907-
_logger.error("Ignoring unknown commit encoding %r", encoding)
907+
# Reject malformed names and non-text codecs without changing
908+
# the current encoding (the default unless a valid header was read).
909+
_logger.error("Ignoring invalid commit encoding %r", raw_encoding)
908910
else:
909911
self.encoding = encoding
910912
elif buf[0:7] == b"gpgsig ":

‎test/test_commit.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,26 @@ def test_deserialization_unknown_declared_encoding(self):
493493
self.assertEqual(cmt.author.name, "Andr�")
494494
self.assertEqual(cmt.message, "R�sum�\n")
495495

496+
def test_deserialization_multiple_encoding_headers(self):
497+
for headers in (
498+
b"encoding utf-16-be\nencoding ISO-8859-1\n",
499+
b"encoding ISO-8859-1\nencoding utf-\xff8\n",
500+
):
501+
with self.subTest(headers=headers):
502+
data = (
503+
b"tree 3385f7b1e5f91930a3bd3e07105e113fca29981d\n"
504+
b"author Andr\xe9 <andre@example.com> 1112591163 +0200\n"
505+
b"committer Andr\xe9 <andre@example.com> 1112591163 +0200\n" + headers + b"\n"
506+
b"R\xe9sum\xe9\n"
507+
)
508+
cmt = self.rorepo.commit()
509+
cmt._deserialize(BytesIO(data))
510+
511+
self.assertEqual(cmt.encoding, "ISO-8859-1")
512+
self.assertEqual(cmt.author.name, "André")
513+
self.assertEqual(cmt.committer.name, "André")
514+
self.assertEqual(cmt.message, "Résumé\n")
515+
496516
@with_rw_directory
497517
def test_identity_cannot_alter_headers(self, rw_dir):
498518
"""A name or email must not add header lines or present another identity."""

0 commit comments

Comments
 (0)