@@ -860,31 +860,60 @@ static int verify_headers(const void *data, unsigned long size,
860860 FSCK_MSG_UNTERMINATED_HEADER , "unterminated header" );
861861}
862862
863- static int fsck_ident (const char * * ident ,
863+ static timestamp_t parse_timestamp_from_buf (const char * * start , const char * end )
864+ {
865+ const char * p = * start ;
866+ char buf [24 ]; /* big enough for 2^64 */
867+ size_t i = 0 ;
868+
869+ while (p < end && isdigit (* p )) {
870+ if (i >= ARRAY_SIZE (buf ) - 1 )
871+ return TIME_MAX ;
872+ buf [i ++ ] = * p ++ ;
873+ }
874+ buf [i ] = '\0' ;
875+ * start = p ;
876+ return parse_timestamp (buf , NULL , 10 );
877+ }
878+
879+ static int fsck_ident (const char * * ident , const char * ident_end ,
864880 const struct object_id * oid , enum object_type type ,
865881 struct fsck_options * options )
866882{
867883 const char * p = * ident ;
868- char * end ;
884+ const char * nl ;
869885
870- * ident = strchrnul (* ident , '\n' );
871- if (* * ident == '\n' )
872- (* ident )++ ;
886+ nl = memchr (p , '\n' , ident_end - p );
887+ if (!nl )
888+ BUG ("verify_headers() should have made sure we have a newline" );
889+ * ident = nl + 1 ;
873890
874891 if (* p == '<' )
875892 return report (options , oid , type , FSCK_MSG_MISSING_NAME_BEFORE_EMAIL , "invalid author/committer line - missing space before email" );
876- p += strcspn (p , "<>\n" );
877- if (* p == '>' )
878- return report (options , oid , type , FSCK_MSG_BAD_NAME , "invalid author/committer line - bad name" );
879- if (* p != '<' )
880- return report (options , oid , type , FSCK_MSG_MISSING_EMAIL , "invalid author/committer line - missing email" );
893+ for (;;) {
894+ if (p >= ident_end || * p == '\n' )
895+ return report (options , oid , type , FSCK_MSG_MISSING_EMAIL , "invalid author/committer line - missing email" );
896+ if (* p == '>' )
897+ return report (options , oid , type , FSCK_MSG_BAD_NAME , "invalid author/committer line - bad name" );
898+ if (* p == '<' )
899+ break ; /* end of name, beginning of email */
900+
901+ /* otherwise, skip past arbitrary name char */
902+ p ++ ;
903+ }
881904 if (p [-1 ] != ' ' )
882905 return report (options , oid , type , FSCK_MSG_MISSING_SPACE_BEFORE_EMAIL , "invalid author/committer line - missing space before email" );
883- p ++ ;
884- p += strcspn (p , "<>\n" );
885- if (* p != '>' )
886- return report (options , oid , type , FSCK_MSG_BAD_EMAIL , "invalid author/committer line - bad email" );
887- p ++ ;
906+ p ++ ; /* skip past '<' we found */
907+ for (;;) {
908+ if (p >= ident_end || * p == '<' || * p == '\n' )
909+ return report (options , oid , type , FSCK_MSG_BAD_EMAIL , "invalid author/committer line - bad email" );
910+ if (* p == '>' )
911+ break ; /* end of email */
912+
913+ /* otherwise, skip past arbitrary email char */
914+ p ++ ;
915+ }
916+ p ++ ; /* skip past '>' we found */
888917 if (* p != ' ' )
889918 return report (options , oid , type , FSCK_MSG_MISSING_SPACE_BEFORE_DATE , "invalid author/committer line - missing space before date" );
890919 p ++ ;
@@ -904,11 +933,11 @@ static int fsck_ident(const char **ident,
904933 "invalid author/committer line - bad date" );
905934 if (* p == '0' && p [1 ] != ' ' )
906935 return report (options , oid , type , FSCK_MSG_ZERO_PADDED_DATE , "invalid author/committer line - zero-padded date" );
907- if (date_overflows (parse_timestamp ( p , & end , 10 )))
936+ if (date_overflows (parse_timestamp_from_buf ( & p , ident_end )))
908937 return report (options , oid , type , FSCK_MSG_BAD_DATE_OVERFLOW , "invalid author/committer line - date causes integer overflow" );
909- if (( end == p || * end != ' ' ) )
938+ if (* p != ' ' )
910939 return report (options , oid , type , FSCK_MSG_BAD_DATE , "invalid author/committer line - bad date" );
911- p = end + 1 ;
940+ p ++ ;
912941 if ((* p != '+' && * p != '-' ) ||
913942 !isdigit (p [1 ]) ||
914943 !isdigit (p [2 ]) ||
@@ -958,7 +987,7 @@ static int fsck_commit(const struct object_id *oid,
958987 author_count = 0 ;
959988 while (buffer < buffer_end && skip_prefix (buffer , "author " , & buffer )) {
960989 author_count ++ ;
961- err = fsck_ident (& buffer , oid , OBJ_COMMIT , options );
990+ err = fsck_ident (& buffer , buffer_end , oid , OBJ_COMMIT , options );
962991 if (err )
963992 return err ;
964993 }
@@ -970,7 +999,7 @@ static int fsck_commit(const struct object_id *oid,
970999 return err ;
9711000 if (buffer >= buffer_end || !skip_prefix (buffer , "committer " , & buffer ))
9721001 return report (options , oid , OBJ_COMMIT , FSCK_MSG_MISSING_COMMITTER , "invalid format - expected 'committer' line" );
973- err = fsck_ident (& buffer , oid , OBJ_COMMIT , options );
1002+ err = fsck_ident (& buffer , buffer_end , oid , OBJ_COMMIT , options );
9741003 if (err )
9751004 return err ;
9761005 if (memchr (buffer_begin , '\0' , size )) {
@@ -1065,7 +1094,7 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer,
10651094 goto done ;
10661095 }
10671096 else
1068- ret = fsck_ident (& buffer , oid , OBJ_TAG , options );
1097+ ret = fsck_ident (& buffer , buffer_end , oid , OBJ_TAG , options );
10691098
10701099 if (buffer < buffer_end && (skip_prefix (buffer , "gpgsig " , & buffer ) || skip_prefix (buffer , "gpgsig-sha256 " , & buffer ))) {
10711100 eol = memchr (buffer , '\n' , buffer_end - buffer );
0 commit comments