@@ -1854,33 +1854,76 @@ static int match_fragment(struct image *img,
1854
1854
{
1855
1855
int i ;
1856
1856
char * fixed_buf , * buf , * orig , * target ;
1857
+ int preimage_limit ;
1857
1858
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
+ */
1859
1882
return 0 ;
1883
+ }
1860
1884
1861
1885
if (match_beginning && try_lno )
1862
1886
return 0 ;
1863
1887
1864
- if (match_end && preimage -> nr + try_lno != img -> nr )
1865
- return 0 ;
1866
-
1867
1888
/* Quick hash check */
1868
- for (i = 0 ; i < preimage -> nr ; i ++ )
1889
+ for (i = 0 ; i < preimage_limit ; i ++ )
1869
1890
if (preimage -> line [i ].hash != img -> line [try_lno + i ].hash )
1870
1891
return 0 ;
1871
1892
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
+ }
1884
1927
1885
1928
/*
1886
1929
* No exact match. If we are ignoring whitespace, run a line-by-line
@@ -1891,7 +1934,10 @@ static int match_fragment(struct image *img,
1891
1934
size_t imgoff = 0 ;
1892
1935
size_t preoff = 0 ;
1893
1936
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 ++ ) {
1895
1941
size_t prelen = preimage -> line [i ].len ;
1896
1942
size_t imglen = img -> line [try_lno + i ].len ;
1897
1943
@@ -1905,20 +1951,36 @@ static int match_fragment(struct image *img,
1905
1951
}
1906
1952
1907
1953
/*
1908
- * Ok, the preimage matches with whitespace fuzz. Update it and
1909
- * the common postimage lines to use the same whitespace as the
1910
- * target. imgoff now holds the true length of the target that
1911
- * matches the preimage, and we need to update the line lengths
1912
- * of the preimage to match the target ones.
1954
+ * Ok, the preimage matches with whitespace fuzz.
1955
+ *
1956
+ * imgoff now holds the true length of the target that
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.)
1913
1963
*/
1914
- fixed_buf = xmalloc (imgoff );
1915
- memcpy (fixed_buf , img -> buf + try , imgoff );
1916
- for (i = 0 ; i < preimage -> nr ; i ++ )
1917
- preimage -> line [i ].len = img -> line [try_lno + i ].len ;
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 ;
1918
1971
1919
1972
/*
1920
- * Update the preimage buffer and the postimage context lines.
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.
1921
1978
*/
1979
+ extra_chars = preimage_end - preimage_eof ;
1980
+ fixed_buf = xmalloc (imgoff + extra_chars );
1981
+ memcpy (fixed_buf , img -> buf + try , imgoff );
1982
+ memcpy (fixed_buf + imgoff , preimage_eof , extra_chars );
1983
+ imgoff += extra_chars ;
1922
1984
update_pre_post_images (preimage , postimage ,
1923
1985
fixed_buf , imgoff , postlen );
1924
1986
return 1 ;
@@ -1932,12 +1994,16 @@ static int match_fragment(struct image *img,
1932
1994
* it might with whitespace fuzz. We haven't been asked to
1933
1995
* ignore whitespace, we were asked to correct whitespace
1934
1996
* 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.
1935
2001
*/
1936
2002
fixed_buf = xmalloc (preimage -> len + 1 );
1937
2003
buf = fixed_buf ;
1938
2004
orig = preimage -> buf ;
1939
2005
target = img -> buf + try ;
1940
- for (i = 0 ; i < preimage -> nr ; i ++ ) {
2006
+ for (i = 0 ; i < preimage_limit ; i ++ ) {
1941
2007
size_t fixlen ; /* length after fixing the preimage */
1942
2008
size_t oldlen = preimage -> line [i ].len ;
1943
2009
size_t tgtlen = img -> line [try_lno + i ].len ;
@@ -1977,6 +2043,29 @@ static int match_fragment(struct image *img,
1977
2043
target += tgtlen ;
1978
2044
}
1979
2045
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
+
1980
2069
/*
1981
2070
* Yes, the preimage is based on an older version that still
1982
2071
* has whitespace breakages unfixed, and fixing them makes the
@@ -2002,9 +2091,6 @@ static int find_pos(struct image *img,
2002
2091
unsigned long backwards , forwards , try ;
2003
2092
int backwards_lno , forwards_lno , try_lno ;
2004
2093
2005
- if (preimage -> nr > img -> nr )
2006
- return -1 ;
2007
-
2008
2094
/*
2009
2095
* If match_beginning or match_end is specified, there is no
2010
2096
* point starting from a wrong line that will never match and
@@ -2015,7 +2101,12 @@ static int find_pos(struct image *img,
2015
2101
else if (match_end )
2016
2102
line = img -> nr - preimage -> nr ;
2017
2103
2018
- if (line > img -> nr )
2104
+ /*
2105
+ * Because the comparison is unsigned, the following test
2106
+ * will also take care of a negative line number that can
2107
+ * result when match_end and preimage is larger than the target.
2108
+ */
2109
+ if ((size_t ) line > img -> nr )
2019
2110
line = img -> nr ;
2020
2111
2021
2112
try = 0 ;
@@ -2091,12 +2182,26 @@ static void update_image(struct image *img,
2091
2182
int i , nr ;
2092
2183
size_t remove_count , insert_count , applied_at = 0 ;
2093
2184
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 ;
2094
2199
2095
2200
for (i = 0 ; i < applied_pos ; i ++ )
2096
2201
applied_at += img -> line [i ].len ;
2097
2202
2098
2203
remove_count = 0 ;
2099
- for (i = 0 ; i < preimage -> nr ; i ++ )
2204
+ for (i = 0 ; i < preimage_limit ; i ++ )
2100
2205
remove_count += img -> line [applied_pos + i ].len ;
2101
2206
insert_count = postimage -> len ;
2102
2207
@@ -2113,19 +2218,19 @@ static void update_image(struct image *img,
2113
2218
result [img -> len ] = '\0' ;
2114
2219
2115
2220
/* Adjust the line table */
2116
- nr = img -> nr + postimage -> nr - preimage -> nr ;
2117
- if (preimage -> nr < postimage -> nr ) {
2221
+ nr = img -> nr + postimage -> nr - preimage_limit ;
2222
+ if (preimage_limit < postimage -> nr ) {
2118
2223
/*
2119
2224
* NOTE: this knows that we never call remove_first_line()
2120
2225
* on anything other than pre/post image.
2121
2226
*/
2122
2227
img -> line = xrealloc (img -> line , nr * sizeof (* img -> line ));
2123
2228
img -> line_allocated = img -> line ;
2124
2229
}
2125
- if (preimage -> nr != postimage -> nr )
2230
+ if (preimage_limit != postimage -> nr )
2126
2231
memmove (img -> line + applied_pos + postimage -> nr ,
2127
- img -> line + applied_pos + preimage -> nr ,
2128
- (img -> nr - (applied_pos + preimage -> nr )) *
2232
+ img -> line + applied_pos + preimage_limit ,
2233
+ (img -> nr - (applied_pos + preimage_limit )) *
2129
2234
sizeof (* img -> line ));
2130
2235
memcpy (img -> line + applied_pos ,
2131
2236
postimage -> line ,
@@ -2321,7 +2426,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
2321
2426
2322
2427
if (applied_pos >= 0 ) {
2323
2428
if (new_blank_lines_at_end &&
2324
- preimage .nr + applied_pos = = img -> nr &&
2429
+ preimage .nr + applied_pos > = img -> nr &&
2325
2430
(ws_rule & WS_BLANK_AT_EOF ) &&
2326
2431
ws_error_action != nowarn_ws_error ) {
2327
2432
record_ws_error (WS_BLANK_AT_EOF , "+" , 1 , frag -> linenr );
0 commit comments