Hi, the hunk size is basically limitated to MAXHUNKSIZE, although the implementation consideres it as a soft limit: it's possible to get one step above this limit. It's set to 100,000 but hunkmax can be legally set to 128,000...
This diff unifies the grow check and avoids calling realloc() again and again until enough space is available. Instead, it calculates the size once and therefore calls the realloc()s only once, too. The point of this diff is to cover the cases in which MAXHUNKSIZE is not checked. Having a slightly better performance is just an additional benefit. Tobias Index: pch.c =================================================================== RCS file: /cvs/src/usr.bin/patch/pch.c,v retrieving revision 1.42 diff -u -p -r1.42 pch.c --- pch.c 17 Nov 2014 10:58:09 -0000 1.42 +++ pch.c 17 Nov 2014 15:26:38 -0000 @@ -68,7 +68,7 @@ static LINENUM p_bfake = -1; /* beg of f static FILE *pfp = NULL; /* patch file pointer */ static char *bestguess = NULL; /* guess at correct filename */ -static void grow_hunkmax(void); +static void grow_hunkmax(int); static int intuit_diff_type(void); static void next_intuit_at(off_t, LINENUM); static void skip_to(off_t, LINENUM); @@ -134,17 +134,23 @@ set_hunkmax(void) } /* - * Enlarge the arrays containing the current hunk of patch. + * Enlarge the arrays containing the current hunk of patch for the + * specified amount of lines. */ static void -grow_hunkmax(void) +grow_hunkmax(int req_size) { int new_hunkmax; char **new_p_line; short *new_p_len; char *new_p_char; - new_hunkmax = hunkmax * 2; + if (req_size > MAXHUNKSIZE) + fatal("hunk too large (%ld lines) at line %ld: %s", + req_size, p_input_line, buf); + + for (new_hunkmax = hunkmax; req_size >= new_hunkmax; new_hunkmax *= 2) + ; if (p_line == NULL || p_len == NULL || p_char == NULL) fatal("Internal memory allocation error\n"); @@ -595,8 +601,8 @@ another_hunk(void) /* we need this much at least */ p_max = p_ptrn_lines + 6; - while (p_max >= hunkmax) - grow_hunkmax(); + if (p_max >= hunkmax) + grow_hunkmax(p_max); p_max = hunkmax; break; case '-': @@ -662,11 +668,8 @@ another_hunk(void) p_newfirst = 1; } p_max = p_repl_lines + p_end; - if (p_max > MAXHUNKSIZE) - fatal("hunk too large (%ld lines) at line %ld: %s", - p_max, p_input_line, buf); - while (p_max >= hunkmax) - grow_hunkmax(); + if (p_max >= hunkmax) + grow_hunkmax(p_max); if (p_repl_lines != ptrn_copiable && (p_context != 0 || p_repl_lines != 1)) repl_could_be_missing = false; @@ -882,8 +885,8 @@ hunk_done: if (!p_ptrn_lines) p_first++; /* do append rather than insert */ p_max = p_ptrn_lines + p_repl_lines + 1; - while (p_max >= hunkmax) - grow_hunkmax(); + if (p_max >= hunkmax) + grow_hunkmax(p_max); fillsrc = 1; filldst = fillsrc + p_ptrn_lines; p_end = filldst + p_repl_lines; @@ -1040,11 +1043,8 @@ hunk_done: if (hunk_type == 'd') min++; p_end = p_ptrn_lines + 1 + max - min + 1; - if (p_end > MAXHUNKSIZE) - fatal("hunk too large (%ld lines) at line %ld: %s", - p_end, p_input_line, buf); - while (p_end >= hunkmax) - grow_hunkmax(); + if (p_end >= hunkmax) + grow_hunkmax(p_end); p_newfirst = min; p_repl_lines = max - min + 1; snprintf(buf, sizeof buf, "*** %ld,%ld\n", p_first,