@@ -1854,33 +1854,76 @@ static int match_fragment(struct image *img,
18541854{
18551855 int i ;
18561856 char * fixed_buf , * buf , * orig , * target ;
1857+ int preimage_limit ;
18571858
1858- if (preimage -> nr + try_lno > img -> nr )
1859+ if (preimage -> nr + try_lno <= img -> nr ) {
1860+ /*
1861+ * The hunk falls within the boundaries of img.
1862+ */
1863+ preimage_limit = preimage -> nr ;
1864+ if (match_end && (preimage -> nr + try_lno != img -> nr ))
1865+ return 0 ;
1866+ } else if (ws_error_action == correct_ws_error &&
1867+ (ws_rule & WS_BLANK_AT_EOF ) && match_end ) {
1868+ /*
1869+ * This hunk that matches at the end extends beyond
1870+ * the end of img, and we are removing blank lines
1871+ * at the end of the file. This many lines from the
1872+ * beginning of the preimage must match with img, and
1873+ * the remainder of the preimage must be blank.
1874+ */
1875+ preimage_limit = img -> nr - try_lno ;
1876+ } else {
1877+ /*
1878+ * The hunk extends beyond the end of the img and
1879+ * we are not removing blanks at the end, so we
1880+ * should reject the hunk at this position.
1881+ */
18591882 return 0 ;
1883+ }
18601884
18611885 if (match_beginning && try_lno )
18621886 return 0 ;
18631887
1864- if (match_end && preimage -> nr + try_lno != img -> nr )
1865- return 0 ;
1866-
18671888 /* Quick hash check */
1868- for (i = 0 ; i < preimage -> nr ; i ++ )
1889+ for (i = 0 ; i < preimage_limit ; i ++ )
18691890 if (preimage -> line [i ].hash != img -> line [try_lno + i ].hash )
18701891 return 0 ;
18711892
1872- /*
1873- * Do we have an exact match? If we were told to match
1874- * at the end, size must be exactly at try+fragsize,
1875- * otherwise try+fragsize must be still within the preimage,
1876- * and either case, the old piece should match the preimage
1877- * exactly.
1878- */
1879- if ((match_end
1880- ? (try + preimage -> len == img -> len )
1881- : (try + preimage -> len <= img -> len )) &&
1882- !memcmp (img -> buf + try , preimage -> buf , preimage -> len ))
1883- return 1 ;
1893+ if (preimage_limit == preimage -> nr ) {
1894+ /*
1895+ * Do we have an exact match? If we were told to match
1896+ * at the end, size must be exactly at try+fragsize,
1897+ * otherwise try+fragsize must be still within the preimage,
1898+ * and either case, the old piece should match the preimage
1899+ * exactly.
1900+ */
1901+ if ((match_end
1902+ ? (try + preimage -> len == img -> len )
1903+ : (try + preimage -> len <= img -> len )) &&
1904+ !memcmp (img -> buf + try , preimage -> buf , preimage -> len ))
1905+ return 1 ;
1906+ } else {
1907+ /*
1908+ * The preimage extends beyond the end of img, so
1909+ * there cannot be an exact match.
1910+ *
1911+ * There must be one non-blank context line that match
1912+ * a line before the end of img.
1913+ */
1914+ char * buf_end ;
1915+
1916+ buf = preimage -> buf ;
1917+ buf_end = buf ;
1918+ for (i = 0 ; i < preimage_limit ; i ++ )
1919+ buf_end += preimage -> line [i ].len ;
1920+
1921+ for ( ; buf < buf_end ; buf ++ )
1922+ if (!isspace (* buf ))
1923+ break ;
1924+ if (buf == buf_end )
1925+ return 0 ;
1926+ }
18841927
18851928 /*
18861929 * No exact match. If we are ignoring whitespace, run a line-by-line
@@ -1891,7 +1934,10 @@ static int match_fragment(struct image *img,
18911934 size_t imgoff = 0 ;
18921935 size_t preoff = 0 ;
18931936 size_t postlen = postimage -> len ;
1894- for (i = 0 ; i < preimage -> nr ; i ++ ) {
1937+ size_t extra_chars ;
1938+ char * preimage_eof ;
1939+ char * preimage_end ;
1940+ for (i = 0 ; i < preimage_limit ; i ++ ) {
18951941 size_t prelen = preimage -> line [i ].len ;
18961942 size_t imglen = img -> line [try_lno + i ].len ;
18971943
@@ -1908,12 +1954,33 @@ static int match_fragment(struct image *img,
19081954 * Ok, the preimage matches with whitespace fuzz.
19091955 *
19101956 * imgoff now holds the true length of the target that
1911- * matches the preimage. Update the preimage and
1912- * the common postimage context lines to use the same
1913- * whitespace as the target.
1957+ * matches the preimage before the end of the file.
1958+ *
1959+ * Count the number of characters in the preimage that fall
1960+ * beyond the end of the file and make sure that all of them
1961+ * are whitespace characters. (This can only happen if
1962+ * we are removing blank lines at the end of the file.)
19141963 */
1915- fixed_buf = xmalloc (imgoff );
1964+ buf = preimage_eof = preimage -> buf + preoff ;
1965+ for ( ; i < preimage -> nr ; i ++ )
1966+ preoff += preimage -> line [i ].len ;
1967+ preimage_end = preimage -> buf + preoff ;
1968+ for ( ; buf < preimage_end ; buf ++ )
1969+ if (!isspace (* buf ))
1970+ return 0 ;
1971+
1972+ /*
1973+ * Update the preimage and the common postimage context
1974+ * lines to use the same whitespace as the target.
1975+ * If whitespace is missing in the target (i.e.
1976+ * if the preimage extends beyond the end of the file),
1977+ * use the whitespace from the preimage.
1978+ */
1979+ extra_chars = preimage_end - preimage_eof ;
1980+ fixed_buf = xmalloc (imgoff + extra_chars );
19161981 memcpy (fixed_buf , img -> buf + try , imgoff );
1982+ memcpy (fixed_buf + imgoff , preimage_eof , extra_chars );
1983+ imgoff += extra_chars ;
19171984 update_pre_post_images (preimage , postimage ,
19181985 fixed_buf , imgoff , postlen );
19191986 return 1 ;
@@ -1927,12 +1994,16 @@ static int match_fragment(struct image *img,
19271994 * it might with whitespace fuzz. We haven't been asked to
19281995 * ignore whitespace, we were asked to correct whitespace
19291996 * errors, so let's try matching after whitespace correction.
1997+ *
1998+ * The preimage may extend beyond the end of the file,
1999+ * but in this loop we will only handle the part of the
2000+ * preimage that falls within the file.
19302001 */
19312002 fixed_buf = xmalloc (preimage -> len + 1 );
19322003 buf = fixed_buf ;
19332004 orig = preimage -> buf ;
19342005 target = img -> buf + try ;
1935- for (i = 0 ; i < preimage -> nr ; i ++ ) {
2006+ for (i = 0 ; i < preimage_limit ; i ++ ) {
19362007 size_t fixlen ; /* length after fixing the preimage */
19372008 size_t oldlen = preimage -> line [i ].len ;
19382009 size_t tgtlen = img -> line [try_lno + i ].len ;
@@ -1972,6 +2043,29 @@ static int match_fragment(struct image *img,
19722043 target += tgtlen ;
19732044 }
19742045
2046+
2047+ /*
2048+ * Now handle the lines in the preimage that falls beyond the
2049+ * end of the file (if any). They will only match if they are
2050+ * empty or only contain whitespace (if WS_BLANK_AT_EOL is
2051+ * false).
2052+ */
2053+ for ( ; i < preimage -> nr ; i ++ ) {
2054+ size_t fixlen ; /* length after fixing the preimage */
2055+ size_t oldlen = preimage -> line [i ].len ;
2056+ int j ;
2057+
2058+ /* Try fixing the line in the preimage */
2059+ fixlen = ws_fix_copy (buf , orig , oldlen , ws_rule , NULL );
2060+
2061+ for (j = 0 ; j < fixlen ; j ++ )
2062+ if (!isspace (buf [j ]))
2063+ goto unmatch_exit ;
2064+
2065+ orig += oldlen ;
2066+ buf += fixlen ;
2067+ }
2068+
19752069 /*
19762070 * Yes, the preimage is based on an older version that still
19772071 * has whitespace breakages unfixed, and fixing them makes the
@@ -2088,12 +2182,26 @@ static void update_image(struct image *img,
20882182 int i , nr ;
20892183 size_t remove_count , insert_count , applied_at = 0 ;
20902184 char * result ;
2185+ int preimage_limit ;
2186+
2187+ /*
2188+ * If we are removing blank lines at the end of img,
2189+ * the preimage may extend beyond the end.
2190+ * If that is the case, we must be careful only to
2191+ * remove the part of the preimage that falls within
2192+ * the boundaries of img. Initialize preimage_limit
2193+ * to the number of lines in the preimage that falls
2194+ * within the boundaries.
2195+ */
2196+ preimage_limit = preimage -> nr ;
2197+ if (preimage_limit > img -> nr - applied_pos )
2198+ preimage_limit = img -> nr - applied_pos ;
20912199
20922200 for (i = 0 ; i < applied_pos ; i ++ )
20932201 applied_at += img -> line [i ].len ;
20942202
20952203 remove_count = 0 ;
2096- for (i = 0 ; i < preimage -> nr ; i ++ )
2204+ for (i = 0 ; i < preimage_limit ; i ++ )
20972205 remove_count += img -> line [applied_pos + i ].len ;
20982206 insert_count = postimage -> len ;
20992207
@@ -2110,19 +2218,19 @@ static void update_image(struct image *img,
21102218 result [img -> len ] = '\0' ;
21112219
21122220 /* Adjust the line table */
2113- nr = img -> nr + postimage -> nr - preimage -> nr ;
2114- if (preimage -> nr < postimage -> nr ) {
2221+ nr = img -> nr + postimage -> nr - preimage_limit ;
2222+ if (preimage_limit < postimage -> nr ) {
21152223 /*
21162224 * NOTE: this knows that we never call remove_first_line()
21172225 * on anything other than pre/post image.
21182226 */
21192227 img -> line = xrealloc (img -> line , nr * sizeof (* img -> line ));
21202228 img -> line_allocated = img -> line ;
21212229 }
2122- if (preimage -> nr != postimage -> nr )
2230+ if (preimage_limit != postimage -> nr )
21232231 memmove (img -> line + applied_pos + postimage -> nr ,
2124- img -> line + applied_pos + preimage -> nr ,
2125- (img -> nr - (applied_pos + preimage -> nr )) *
2232+ img -> line + applied_pos + preimage_limit ,
2233+ (img -> nr - (applied_pos + preimage_limit )) *
21262234 sizeof (* img -> line ));
21272235 memcpy (img -> line + applied_pos ,
21282236 postimage -> line ,
@@ -2318,7 +2426,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
23182426
23192427 if (applied_pos >= 0 ) {
23202428 if (new_blank_lines_at_end &&
2321- preimage .nr + applied_pos = = img -> nr &&
2429+ preimage .nr + applied_pos > = img -> nr &&
23222430 (ws_rule & WS_BLANK_AT_EOF ) &&
23232431 ws_error_action != nowarn_ws_error ) {
23242432 record_ws_error (WS_BLANK_AT_EOF , "+" , 1 , frag -> linenr );
0 commit comments