@@ -424,6 +424,49 @@ def test_invalid_commit(self):
424424 self .assertEqual (cmt .author .name , "E.Azer Ko�o�o�oculu" , cmt .author .name )
425425 self .assertEqual (cmt .author .email , "azer@kodfabrik.com" , cmt .author .email )
426426
427+ @with_rw_directory
428+ def test_identity_cannot_alter_headers (self , rw_dir ):
429+ """A name or email must not add header lines or present another identity."""
430+ rw_repo = Repo .init (osp .join (rw_dir , "test_identity_headers" ))
431+ path = osp .join (str (rw_repo .working_tree_dir ), "hello.txt" )
432+ touch (path )
433+ rw_repo .index .add ([path ])
434+ tree = rw_repo .index .write_tree ()
435+ service = Actor ("Service" , "service@example.com" )
436+ forged = "committer Forged <forged@example.com> 0 +0000"
437+
438+ for name , email in (
439+ # A line feed ends the header line, so the remainder would become headers
440+ # of its own, which Git reads before the committer written after them.
441+ ("User <user@example.com> 0 +0000\n " + forged , "user@example.com" ),
442+ ("User" , "user@example.com> 0 +0000\n " + forged ),
443+ # Angle brackets delimit the email, so these would present another one.
444+ ("Forged <forged@example.com>" , "user@example.com" ),
445+ ("User" , "forged@example.com> <user@example.com" ),
446+ ("User>" , "user@example.com" ),
447+ ("User" , "<user@example.com" ),
448+ ):
449+ with self .subTest (name = name , email = email ):
450+ identity = Actor (name , email )
451+ with self .assertRaises (ValueError ):
452+ Commit .create_from_tree (rw_repo , tree , "message" , head = True , author = identity , committer = service )
453+ with self .assertRaises (ValueError ):
454+ Commit .create_from_tree (rw_repo , tree , "message" , head = True , author = service , committer = identity )
455+
456+ # Nothing was committed along the way.
457+ assert not rw_repo .head .is_valid ()
458+
459+ # Other punctuation is still written as given.
460+ author = Actor ("Dr. J. O'Neil-Smith, Jr." , "user+tag@example.com" )
461+ commit = Commit .create_from_tree (rw_repo , tree , "message" , head = True , author = author , committer = service )
462+ stored = Commit (rw_repo , commit .binsha )
463+ self .assertEqual (stored .author , author )
464+ self .assertEqual (stored .committer , service )
465+ self .assertEqual (stored .message , "message" )
466+
467+ with self .assertRaises (ValueError ):
468+ commit .replace (author = Actor ("User\n " + forged , "user@example.com" ))
469+
427470 def test_gpgsig (self ):
428471 cmt = self .rorepo .commit ()
429472 with open (fixture_path ("commit_with_gpgsig" ), "rb" ) as fd :
0 commit comments