From: Mark Lodato <hidden> Date: 2016-06-15 22:48:41
In git-fast-import(1), fix a mistake that said LT and LF were the
invalid characters in email addresses. This should have been GT and LF,
since the GT ends the email address and LF ends the command.
Signed-off-by: Mark Lodato <redacted>
---
Documentation/git-fast-import.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
@@ -394,7 +394,7 @@ Here `<name>` is the person's display name (for example and greater-than (\x3e) symbols. These are required to delimit the email address from the other fields in the line. Note that `<name>` is free-form and may contain any sequence of bytes, except-`LT` and `LF`. It is typically UTF-8 encoded.+`GT` and `LF`. It is typically UTF-8 encoded. The time of the change is specified by `<when>` using the date format that was selected by the \--date-format=<fmt> command line option.
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:48:42
Check that email addresses do not contain <, >, or newline so they can
be quickly scanned without trouble. The copy() function in ident.c
already ensures that ordinary git commands will not write email
addresses without this property.
Signed-off-by: Jonathan Nieder <redacted>
---
Thoughts? Should some of these errors be warnings?
git fast-import is capable of producing commits with some of these
problems: for example, it is fine with
committer C O Mitter <foo@b>ar.net> 005 - +5
fsck.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
t/t1450-fsck.sh | 25 +++++++++++++++++++++++++
2 files changed, 72 insertions(+), 0 deletions(-)
@@ -222,12 +222,47 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)returnretval;}+staticintfsck_ident(char**ident,structobject*obj,fsck_errorerror_func)+{+if(**ident=='<'||**ident=='\n')+returnerror_func(obj,FSCK_ERROR,"invalid author/committer line - missing space before email");+*ident+=strcspn(*ident,"<\n");+if((*ident)[-1]!=' ')+returnerror_func(obj,FSCK_ERROR,"invalid author/committer line - missing space before email");+if(**ident!='<')+returnerror_func(obj,FSCK_ERROR,"invalid author/committer line - missing email");+(*ident)++;+*ident+=strcspn(*ident,"<>\n");+if(**ident!='>')+returnerror_func(obj,FSCK_ERROR,"invalid author/committer line - bad email");+(*ident)++;+if(**ident!=' ')+returnerror_func(obj,FSCK_ERROR,"invalid author/committer line - missing space before date");+(*ident)++;+if(**ident=='0'&&(*ident)[1]!=' ')+returnerror_func(obj,FSCK_ERROR,"invalid author/committer line - zero-padded date");+*ident+=strspn(*ident,"0123456789");+if(**ident!=' ')+returnerror_func(obj,FSCK_ERROR,"invalid author/committer line - bad date");+(*ident)++;+if((**ident!='+'&&**ident!='-')||+!isdigit((*ident)[1])||+!isdigit((*ident)[2])||+!isdigit((*ident)[3])||+!isdigit((*ident)[4])||+((*ident)[5]!='\n'))+returnerror_func(obj,FSCK_ERROR,"invalid author/committer line - bad time zone");+(*ident)+=6;+return0;+}+staticintfsck_commit(structcommit*commit,fsck_errorerror_func){char*buffer=commit->buffer;unsignedchartree_sha1[20],sha1[20];structcommit_graft*graft;intparents=0;+interr;if(commit->date==ULONG_MAX)returnerror_func(&commit->object,FSCK_ERROR,"invalid author/committer line");
@@ -266,6 +301,18 @@ static int fsck_commit(struct commit *commit, fsck_error error_func)}if(memcmp(buffer,"author ",7))returnerror_func(&commit->object,FSCK_ERROR,"invalid format - expected 'author' line");+buffer+=7;+err=fsck_ident(&buffer,&commit->object,error_func);+if(err)+returnerr;+if(memcmp(buffer,"committer ",strlen("committer ")))+returnerror_func(&commit->object,FSCK_ERROR,"invalid format - expected 'committer' line");+buffer+=strlen("committer ");+err=fsck_ident(&buffer,&commit->object,error_func);+if(err)+returnerr;+if(*buffer!='\n')+returnerror_func(&commit->object,FSCK_ERROR,"invalid format - expected blank line");if(!commit->tree)returnerror_func(&commit->object,FSCK_ERROR,"could not load commit's tree %s",sha1_to_hex(tree_sha1));
@@ -57,6 +57,31 @@ test_expect_success 'branch pointing to non-commit' 'gitupdate-ref-drefs/heads/invalid'+new=nothing+test_expect_success'email without @ is okay''+gitcat-filecommitHEAD>basis&&+sed"s/@/AT/"basis>okay&&+new=$(githash-object-tcommit-w--stdin<okay)&&+echo"$new"&&+gitupdate-refrefs/heads/bogus"$new"&&+gitfsck+'+gitupdate-ref-drefs/heads/bogus+rm-f".git/objects/$new"++new=nothing+test_expect_success'email with embedded > is not okay''+gitcat-filecommitHEAD>basis&&+sed"s/@[a-z]/&>/"basis>bad-email&&+new=$(githash-object-tcommit-w--stdin<bad-email)&&+echo"$new"&&+gitupdate-refrefs/heads/bogus"$new"&&+gitfsck2>out&&+grep"error in commit $new"out+'+gitupdate-ref-drefs/heads/bogus+rm-f".git/objects/$new"+ cat>invalid-tag<<EOF objectfffffffffffffffffffffffffffffffffffffffftypecommit
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:48:42
Hi Mark,
Mark Lodato wrote:
quoted hunk
+++ b/Documentation/git-fast-import.txt
@@ -394,7 +394,7 @@ Here `<name>` is the person's display name (for example and greater-than (\x3e) symbols. These are required to delimit the email address from the other fields in the line. Note that `<name>` is free-form and may contain any sequence of bytes, except-`LT` and `LF`. It is typically UTF-8 encoded.+`GT` and `LF`. It is typically UTF-8 encoded.
Here <name> is the person’s display name (for example
“Com M Itter”)
So the original text is correct --- a <name> cannot contain LT because
a less-than sign marks the boundary between a name and email address.
Maybe you were wondering what characters are valid in an e-mail address?
The comments in fast-import.c and code in ident.c are consistent about
this: the forbidden characters are <, >, and LF, though no one seems to
check (see also my other reply). A patch to explain this (including a
reference to git-commit-tree(1), I guess) might be useful.
git won’t understand an email with embedded > or LF. I’m not sure a <
would cause problems, but I don’t mind that it is disallowed.
Hope that helps,
Jonathan
@@ -64,7 +64,9 @@ test_expect_success 'email without @ is okay' 'new=$(githash-object-tcommit-w--stdin<okay)&&echo"$new"&&gitupdate-refrefs/heads/bogus"$new"&&-gitfsck+gitfsck2>out&&+catout&&+!grep"error in commit $new"out' gitupdate-ref-drefs/heads/bogus rm-f".git/objects/$new"
@@ -77,6 +79,7 @@ test_expect_success 'email with embedded > is not okay' 'echo"$new"&&gitupdate-refrefs/heads/bogus"$new"&&gitfsck2>out&&+catout&&grep"error in commit $new"out' gitupdate-ref-drefs/heads/bogus
From: Mark Lodato <hidden> Date: 2016-06-15 22:48:42
On Sat, Apr 24, 2010 at 12:12 PM, Jonathan Nieder [off-list ref] wrote:
Mark Lodato wrote:
quoted
+++ b/Documentation/git-fast-import.txt
@@ -394,7 +394,7 @@ Here `<name>` is the person's display name (for example
and greater-than (\x3e) symbols. These are required to delimit
the email address from the other fields in the line. Note that
`<name>` is free-form and may contain any sequence of bytes, except
-`LT` and `LF`. It is typically UTF-8 encoded.
+`GT` and `LF`. It is typically UTF-8 encoded.
Here <name> is the person’s display name (for example
“Com M Itter”)
So the original text is correct --- a <name> cannot contain LT because
a less-than sign marks the boundary between a name and email address.
Ah, you're right, sorry. I thought it was <email>, not <name>.
Maybe you were wondering what characters are valid in an e-mail address?
The comments in fast-import.c and code in ident.c are consistent about
this: the forbidden characters are <, >, and LF, though no one seems to
check (see also my other reply). A patch to explain this (including a
reference to git-commit-tree(1), I guess) might be useful.
git won’t understand an email with embedded > or LF. I’m not sure a <
would cause problems, but I don’t mind that it is disallowed.
It seems like it would be good to disallow <, >, and LF in both name
and email. With your other patch, > is allowed in the name.
Thanks for the clarification,
Mark
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:48:42
Jonathan Nieder [off-list ref] wrote:
Check that email addresses do not contain <, >, or newline so they can
be quickly scanned without trouble. The copy() function in ident.c
already ensures that ordinary git commands will not write email
addresses without this property.
Signed-off-by: Jonathan Nieder <redacted>
---
Thoughts? Should some of these errors be warnings?
These should be errors. We should never see this sort of thing
occur in a live repository.
git fast-import is capable of producing commits with some of these
problems: for example, it is fine with
committer C O Mitter <foo@b>ar.net> 005 - +5
Yuck. We probably should tighten up the parser in fast-import a
bit more. The above is pretty insane for it to produce into the
repository. I can't even begin to count how many ways the above
line is just wrong... :-)
--
Shawn.
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:48:42
git proper never zero- or space-pads its dates and its time zones are
always 4 digits long. Require fast-import front-ends to behave
likewise to avoid generating puzzling objects.
Since this makes the input format more strict, some front-ends may not
be happy. But they were warned:
This is the Git native format and is <time> SP <offutc>. It is also
fast-import’s default format, if --date-format was not specified.
Unlike the rfc2822 format, this format is very strict. Any variation
in formatting will cause fast-import to reject the value.
Aside from ensuring the format is predictable so tools like git can
handle it, making the date format this strict ensures that there is
only one valid representation for a given date and time zone, which
would be useful for round-trip conversion of objects to and from other
formats (for storage by other version control systems, for example).
Signed-off-by: Jonathan Nieder <redacted>
---
Is -0000 the same time zone as +0000? I wasn’t sure so I erred on the
side of not worrying about it.
fast-import.c | 9 +++++++--
t/t9300-fast-import.sh | 30 ++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+), 2 deletions(-)
@@ -348,6 +348,36 @@ test_expect_success \ cat>input<<INPUT_END commitrefs/heads/branch+author$GIT_AUTHOR_NAME<$GIT_AUTHOR_EMAIL>1170783301-0500+committer$GIT_COMMITTER_NAME<$GIT_COMMITTER_EMAIL>117078330-0500+data<<COMMIT+Malformedtimezone+COMMIT++fromrefs/heads/branch^0++INPUT_END+test_expect_success'E: blanks in raw time zone''+test_must_failgitfast-import--date-format=raw<input+'++cat>input<<INPUT_END+commitrefs/heads/branch+author$GIT_AUTHOR_NAME<$GIT_AUTHOR_EMAIL>01170783301-0500+committer$GIT_COMMITTER_NAME<$GIT_COMMITTER_EMAIL>117078330-0500+data<<COMMIT+Malformeddate+COMMIT++fromrefs/heads/branch^0++INPUT_END+test_expect_success'E: leading zero in raw date''+test_must_failgitfast-import--date-format=raw<input+'++cat>input<<INPUT_END+commitrefs/heads/branch author$GIT_AUTHOR_NAME<$GIT_AUTHOR_EMAIL>TueFeb611:22:182007-0500 committer$GIT_COMMITTER_NAME<$GIT_COMMITTER_EMAIL>TueFeb612:35:022007-0500 data<<COMMIT
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:48:42
The author, committer, and tagger name and email should not include
any embedded <, >, or newline characters. The format of the
identification string is
('author'|'committer'|'tagger') sp name sp < email > sp date
If an object has no name attached, then git expects to find two spaces
in a row.
Helped-by: Mark Lodato [off-list ref]
Signed-off-by: Jonathan Nieder <redacted>
---
For malformed input, the parser in pretty.c and ‘git commit --amend’
tend to end up with different ideas of who the author is. A lot of
the time, commit --amend gives up with "fatal: invalid commit".
Documentation/git-fast-import.txt | 9 ++--
fast-import.c | 54 ++++++++++++++++----------
t/t9300-fast-import.sh | 75 +++++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+), 25 deletions(-)
@@ -393,8 +393,9 @@ Here `<name>` is the person's display name (for example (``cm@example.com''). `LT` and `GT` are the literal less-than (\x3c) and greater-than (\x3e) symbols. These are required to delimit the email address from the other fields in the line. Note that-`<name>` is free-form and may contain any sequence of bytes, except-`LT` and `LF`. It is typically UTF-8 encoded.+`<name>` and `<email>` are free-form and may contain any sequence+of bytes that are not `LT`, `GT`, or `LF`. Both are typically UTF-8+encoded. The time of the change is specified by `<when>` using the date format that was selected by the \--date-format=<fmt> command line option.
@@ -19,8 +19,8 @@ Format of STDIN stream:new_commit::='commit'spref_strlfmark?-('author'(spname)?sp'<'email'>'spwhenlf)?-'committer'(spname)?sp'<'email'>'spwhenlf+('author'spname?sp'<'email'>'spwhenlf)?+'committer'spname?sp'<'email'>'spwhenlfcommit_msg('from'spcommittishlf)?('merge'spcommittishlf)*
@@ -47,7 +47,7 @@ Format of STDIN stream:new_tag::='tag'sptag_strlf'from'spcommittishlf-('tagger'(spname)?sp'<'email'>'spwhenlf)?+('tagger'spname?sp'<'email'>'spwhenlf)?tag_msg;tag_msg::=data;
@@ -123,9 +123,8 @@ Format of STDIN stream:sha1exp::=#AnyvalidGITSHA1expression;hexsha1::=#SHA1inhexadecimalformat;-# note: name and email are UTF8 strings, however name must not-# contain '<' or lf and email must not contain any of the-# following: '<', '>', lf.+# note: name and email are UTF8 strings, however name and email+# must not contain any of the following: '<', '>', lf.#name::=#validGITauthor/committername;email::=#validGITauthor/committeremail;
@@ -1929,34 +1928,47 @@ static int validate_raw_date(const char *src, char *result, int maxlen)return0;}-staticchar*parse_ident(constchar*buf)+staticsize_tparse_name_and_email(constchar*src,char**result,size_textra){-constchar*gt;+constchar*lt,*gt;size_tname_len;-char*ident;-gt=strrchr(buf,'>');-if(!gt)-die("Missing > in ident string: %s",buf);+lt=src+strcspn(src,"<>\n");+if(lt==src||lt[-1]!=' '||*lt!='<')+die("Invalid name in ident string: %s",src);+gt=lt+1+strcspn(lt+1,"<>\n");+if(*gt!='>')+die("Invalid email in ident string: %s",src);gt++;if(*gt!=' ')-die("Missing space after > in ident string: %s",buf);+die("Missing space after > in ident string: %s",src);gt++;-name_len=gt-buf;-ident=xmalloc(name_len+24);-strncpy(ident,buf,name_len);+name_len=gt-src;+*result=xmalloc(name_len+extra);+memcpy(*result,src,name_len);+returnname_len;+}++staticchar*parse_ident(constchar*buf)+{+constchar*date;+size_tname_len;+char*ident;++name_len=parse_name_and_email(buf,&ident,24);+date=buf+name_len;switch(whenspec){caseWHENSPEC_RAW:-if(validate_raw_date(gt,ident+name_len,24)<0)-die("Invalid raw date \"%s\" in ident: %s",gt,buf);+if(validate_raw_date(date,ident+name_len,24)<0)+die("Invalid raw date \"%s\" in ident: %s",date,buf);break;caseWHENSPEC_RFC2822:-if(parse_date(gt,ident+name_len,24)<0)-die("Invalid rfc2822 date \"%s\" in ident: %s",gt,buf);+if(parse_date(date,ident+name_len,24)<0)+die("Invalid rfc2822 date \"%s\" in ident: %s",date,buf);break;caseWHENSPEC_NOW:-if(strcmp("now",gt))+if(strcmp("now",date))die("Date in ident must be 'now': %s",buf);datestamp(ident+name_len,24);break;
From: Shawn O. Pearce <hidden> Date: 2016-06-15 22:48:42
Jonathan Nieder [off-list ref] wrote:
The author, committer, and tagger name and email should not include
any embedded <, >, or newline characters. The format of the
identification string is
('author'|'committer'|'tagger') sp name sp < email > sp date
If an object has no name attached, then git expects to find two spaces
in a row.
This is going to be a problem I think. Some importers are probably
writing "committer <bob> ...." when pulling from systems that don't
have a concept of name vs. email (e.g. CVS or SVN). I highly suspect
that requiring two spaces here will cause a lot of importers to fail.
If we really need to require two spaces, I think we need to honor
the documented input format but rewrite the line inside of the
import process to match the two space convention.
--
Shawn.
From: Jonathan Nieder <hidden> Date: 2016-06-15 22:48:42
Shawn O. Pearce wrote:
Some importers are probably
writing "committer <bob> ...." when pulling from systems that don't
have a concept of name vs. email (e.g. CVS or SVN). I highly suspect
that requiring two spaces here will cause a lot of importers to fail.
If we really need to require two spaces,
It is not a huge deal, but ‘git commit --amend’ will die with "invalid
commit" if it does not find a “ <” sequence after the “author ”
string. Maybe that should be changed. Patch below.
I think we need to honor
the documented input format but rewrite the line inside of the
import process to match the two space convention.
Yes, that’s doable.
Thanks for the feedback,
Jonathan
Err, this will segv when it fails; better to use
lb = a + strlen("\nauthor ");
lb = strchrnul(lb, '<');
rb = strchrnul(lb, '>');
eol = strchrnul(rb, '\n');
if (!*lb || !*rb || !*eol)
die("invalid commit: %s", use_message);
This is even more permissive, but I think that’s okay.
Sorry for the noise.
Jonathan