@@ -69,6 +69,10 @@ static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx, size_t
6969{
7070 int error ;
7171
72+ if (!path_len )
73+ return git_parse_err ("patch contains empty path at line %" PRIuZ ,
74+ ctx -> parse_ctx .line_num );
75+
7276 if ((error = git_buf_put (path , ctx -> parse_ctx .line , path_len )) < 0 )
7377 goto done ;
7478
@@ -91,10 +95,14 @@ static int parse_header_path_buf(git_buf *path, git_patch_parse_ctx *ctx, size_t
9195static int parse_header_path (char * * out , git_patch_parse_ctx * ctx )
9296{
9397 git_buf path = GIT_BUF_INIT ;
94- int error = parse_header_path_buf ( & path , ctx , header_path_len ( ctx )) ;
98+ int error ;
9599
100+ if ((error = parse_header_path_buf (& path , ctx , header_path_len (ctx ))) < 0 )
101+ goto out ;
96102 * out = git_buf_detach (& path );
97103
104+ out :
105+ git_buf_dispose (& path );
98106 return error ;
99107}
100108
@@ -104,6 +112,12 @@ static int parse_header_git_oldpath(
104112 git_buf old_path = GIT_BUF_INIT ;
105113 int error ;
106114
115+ if (patch -> old_path ) {
116+ error = git_parse_err ("patch contains duplicate old path at line %" PRIuZ ,
117+ ctx -> parse_ctx .line_num );
118+ goto out ;
119+ }
120+
107121 if ((error = parse_header_path_buf (& old_path , ctx , ctx -> parse_ctx .line_len - 1 )) < 0 )
108122 goto out ;
109123
@@ -120,9 +134,14 @@ static int parse_header_git_newpath(
120134 git_buf new_path = GIT_BUF_INIT ;
121135 int error ;
122136
123- if ((error = parse_header_path_buf (& new_path , ctx , ctx -> parse_ctx .line_len - 1 )) < 0 )
137+ if (patch -> new_path ) {
138+ error = git_parse_err ("patch contains duplicate new path at line %" PRIuZ ,
139+ ctx -> parse_ctx .line_num );
124140 goto out ;
141+ }
125142
143+ if ((error = parse_header_path_buf (& new_path , ctx , ctx -> parse_ctx .line_len - 1 )) < 0 )
144+ goto out ;
126145 patch -> new_path = git_buf_detach (& new_path );
127146
128147out :
@@ -564,11 +583,17 @@ static int parse_hunk_body(
564583 !git_parse_ctx_contains_s (& ctx -> parse_ctx , "@@ -" );
565584 git_parse_advance_line (& ctx -> parse_ctx )) {
566585
586+ int old_lineno , new_lineno , origin , prefix = 1 ;
567587 char c ;
568- int origin ;
569- int prefix = 1 ;
570- int old_lineno = hunk -> hunk .old_start + (hunk -> hunk .old_lines - oldlines );
571- int new_lineno = hunk -> hunk .new_start + (hunk -> hunk .new_lines - newlines );
588+
589+ if (git__add_int_overflow (& old_lineno , hunk -> hunk .old_start , hunk -> hunk .old_lines ) ||
590+ git__sub_int_overflow (& old_lineno , old_lineno , oldlines ) ||
591+ git__add_int_overflow (& new_lineno , hunk -> hunk .new_start , hunk -> hunk .new_lines ) ||
592+ git__sub_int_overflow (& new_lineno , new_lineno , newlines )) {
593+ error = git_parse_err ("unrepresentable line count at line %" PRIuZ ,
594+ ctx -> parse_ctx .line_num );
595+ goto done ;
596+ }
572597
573598 if (ctx -> parse_ctx .line_len == 0 || ctx -> parse_ctx .line [ctx -> parse_ctx .line_len - 1 ] != '\n' ) {
574599 error = git_parse_err ("invalid patch instruction at line %" PRIuZ ,
@@ -628,6 +653,7 @@ static int parse_hunk_body(
628653
629654 line -> content_len = ctx -> parse_ctx .line_len - prefix ;
630655 line -> content = git__strndup (ctx -> parse_ctx .line + prefix , line -> content_len );
656+ GIT_ERROR_CHECK_ALLOC (line -> content );
631657 line -> content_offset = ctx -> parse_ctx .content_len - ctx -> parse_ctx .remain_len ;
632658 line -> origin = origin ;
633659 line -> num_lines = 1 ;
@@ -667,8 +693,9 @@ static int parse_hunk_body(
667693
668694 memset (line , 0x0 , sizeof (git_diff_line ));
669695
670- line -> content = git__strdup (ctx -> parse_ctx .line );
671696 line -> content_len = ctx -> parse_ctx .line_len ;
697+ line -> content = git__strndup (ctx -> parse_ctx .line , line -> content_len );
698+ GIT_ERROR_CHECK_ALLOC (line -> content );
672699 line -> content_offset = ctx -> parse_ctx .content_len - ctx -> parse_ctx .remain_len ;
673700 line -> origin = eof_for_origin (last_origin );
674701 line -> num_lines = 1 ;
0 commit comments