libdiff: Simplify truncation detection

* Adjust the comment to reflect the fact that SIGBUS can occur not only
  if the file is truncated, but also if an I/O error occurs while paging
  in any part of it.

* Instead of setting a flag, just return EIO.

* Adjust the unit test accordingly.

MFC after:	1 week
Sponsored by:	Klara, Inc.
Reviewed by:	thj, kevans
Differential Revision:	https://reviews.freebsd.org/D55108
This commit is contained in:
Dag-Erling Smørgrav
2026-02-05 15:39:34 +01:00
parent 8c40c7bb36
commit a689bfa4e2
4 changed files with 8 additions and 12 deletions
-1
View File
@@ -118,7 +118,6 @@ struct diff_data {
/* Flags set by file atomizer. */
#define DIFF_ATOMIZER_FOUND_BINARY_DATA 0x00000001
#define DIFF_ATOMIZER_FILE_TRUNCATED 0x00000002
/* Flags set by caller of diff_main(). */
#define DIFF_FLAG_IGNORE_WHITESPACE 0x00000001
+7 -5
View File
@@ -141,6 +141,7 @@ diff_data_atomize_text_lines_mmap(struct diff_data *d)
bool embedded_nul = false;
unsigned int array_size_estimate = d->len / 50;
unsigned int pow2 = 1;
int ret = DIFF_RC_OK;
while (array_size_estimate >>= 1)
pow2++;
@@ -152,13 +153,14 @@ diff_data_atomize_text_lines_mmap(struct diff_data *d)
sigaction(SIGBUS, &act, &oact);
if (sigsetjmp(diff_data_signal_env, 0) > 0) {
/*
* The file was truncated while we were reading it. Set
* the end pointer to the beginning of the line we were
* trying to read, adjust the file length, and set a flag.
* The file was truncated while we were reading it, or an
* I/O error occurred. Set the end pointer to the
* beginning of the line we were trying to read, adjust
* the file length, and set the return value to an error.
*/
end = pos;
d->len = end - d->data;
d->atomizer_flags |= DIFF_ATOMIZER_FILE_TRUNCATED;
ret = EIO;
}
while (pos < end) {
const uint8_t *line_start = pos, *line_end = pos;
@@ -203,7 +205,7 @@ diff_data_atomize_text_lines_mmap(struct diff_data *d)
if (embedded_nul)
d->atomizer_flags |= DIFF_ATOMIZER_FOUND_BINARY_DATA;
return DIFF_RC_OK;
return ret;
}
static int
+1 -2
View File
@@ -45,10 +45,9 @@ ATF_TC_BODY(diff_atomize_truncated, tc)
rewind(f);
ATF_REQUIRE(truncate(fn, size / 2) == 0);
ATF_REQUIRE((p = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fileno(f), 0)) != MAP_FAILED);
ATF_REQUIRE(diff_atomize_file(&d, &cfg, f, p, size, 0) == 0);
ATF_REQUIRE(diff_atomize_file(&d, &cfg, f, p, size, 0) == EIO);
ATF_REQUIRE((size_t)d.len <= size / 2);
ATF_REQUIRE((size_t)d.len >= size / 2 - sizeof(line));
ATF_REQUIRE(d.atomizer_flags & DIFF_ATOMIZER_FILE_TRUNCATED);
}
ATF_TC_CLEANUP(diff_atomize_truncated, tc)
{
-4
View File
@@ -223,14 +223,10 @@ diffreg_new(char *file1, char *file2, int flags, int capsicum)
rc = D_ERROR;
goto done;
}
if (left.atomizer_flags & DIFF_ATOMIZER_FILE_TRUNCATED)
warnx("%s truncated", file1);
if (diff_atomize_file(&right, cfg, f2, (uint8_t *)str2, st2.st_size, diff_flags)) {
rc = D_ERROR;
goto done;
}
if (right.atomizer_flags & DIFF_ATOMIZER_FILE_TRUNCATED)
warnx("%s truncated", file2);
result = diff_main(cfg, &left, &right);
if (result->rc != DIFF_RC_OK) {