Renaud Allard <[email protected]> wrote:
> The p_start+diff_type stall check can be bypassed when
> intuit_diff_type alternates between detecting different
> types at different positions within the same garbage.
>
> Simpler fix: track p_base (the scan start position).
> If it hasn't advanced, stop.
>
> Fuzzed for 5 minutes with UBSan on amd64 and strict
> malloc on i386: 0 crashes. All 20 regression tests pass.
> Although I am not sure the 20 regression tests are sufficient
>
> Index: usr.bin/patch/patch.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/patch/patch.c,v
> retrieving revision 1.78
> diff -u -p -r1.78 patch.c
> --- usr.bin/patch/patch.c 23 Feb 2026 16:40:45 -0000 1.78
> +++ usr.bin/patch/patch.c
> @@ -293,6 +293,12 @@ main(int argc, char *argv[])
> /* for ed script just up and do it and exit */
> if (diff_type == ED_DIFF) {
> do_ed_script();
> + if (ofp)
> + fclose(ofp);
> + ofp = NULL;
> + if (rejfp)
> + fclose(rejfp);
> + rejfp = NULL;
> continue;
> }
this part is okay op@, we need to clean up these files before next
iteration.
> Index: usr.bin/patch/pch.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/patch/pch.c,v
> retrieving revision 1.66
> diff -u -p -r1.66 pch.c
> --- usr.bin/patch/pch.c 12 Jul 2023 15:45:34 -0000 1.66
> +++ usr.bin/patch/pch.c
> @@ -180,6 +180,7 @@ static char *posix_name(const struct fil
> bool
> there_is_another_patch(void)
> {
> + static off_t prev_p_base = -1;
> bool exists = false;
>
> if (p_base != 0 && p_base >= p_filesize) {
> @@ -190,6 +191,12 @@ there_is_another_patch(void)
> if (verbose)
> say("Hmm...");
> diff_type = intuit_diff_type();
> + if (diff_type && p_base == prev_p_base) {
> + if (verbose)
> + say(" Ignoring the trailing garbage.\ndone\n");
> + return false;
> + }
> + prev_p_base = p_base;
> if (!diff_type) {
> if (p_base != 0) {
> if (verbose)
this part I'm less sure. if we're stuck here it means that we're
detecting something but then the rest of the patch machinery fails to
actually consume it, and we loop, am i right?
then, why don't just advance one line, and re-enter intuit_diff_type?
it would guarantee that we reach eof at some point and exit.