aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/libdiff/include/diff_main.h1
-rw-r--r--contrib/libdiff/lib/diff_atomize_text.c35
2 files changed, 31 insertions, 5 deletions
diff --git a/contrib/libdiff/include/diff_main.h b/contrib/libdiff/include/diff_main.h
index 04a6c6e748c9..11700580db4b 100644
--- a/contrib/libdiff/include/diff_main.h
+++ b/contrib/libdiff/include/diff_main.h
@@ -118,6 +118,7 @@ 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
diff --git a/contrib/libdiff/lib/diff_atomize_text.c b/contrib/libdiff/lib/diff_atomize_text.c
index 32023105af94..d8a69733fc00 100644
--- a/contrib/libdiff/lib/diff_atomize_text.c
+++ b/contrib/libdiff/lib/diff_atomize_text.c
@@ -16,6 +16,8 @@
*/
#include <errno.h>
+#include <setjmp.h>
+#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -122,10 +124,18 @@ diff_data_atomize_text_lines_fd(struct diff_data *d)
return DIFF_RC_OK;
}
+static sigjmp_buf diff_data_signal_env;
+static void
+diff_data_signal_handler(int sig)
+{
+ siglongjmp(diff_data_signal_env, sig);
+}
+
static int
diff_data_atomize_text_lines_mmap(struct diff_data *d)
{
- const uint8_t *pos = d->data;
+ struct sigaction act, oact;
+ const uint8_t *volatile pos = d->data;
const uint8_t *end = pos + d->len;
bool ignore_whitespace = (d->diff_flags & DIFF_FLAG_IGNORE_WHITESPACE);
bool embedded_nul = false;
@@ -136,8 +146,22 @@ diff_data_atomize_text_lines_mmap(struct diff_data *d)
ARRAYLIST_INIT(d->atoms, 1 << pow2);
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = diff_data_signal_handler;
+ 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.
+ */
+ end = pos;
+ d->len = end - d->data;
+ d->atomizer_flags |= DIFF_ATOMIZER_FILE_TRUNCATED;
+ }
while (pos < end) {
- const uint8_t *line_end = pos;
+ const uint8_t *line_start = pos, *line_end = pos;
unsigned int hash = 0;
while (line_end < end && *line_end != '\r' && *line_end != '\n') {
@@ -164,15 +188,16 @@ diff_data_atomize_text_lines_mmap(struct diff_data *d)
*atom = (struct diff_atom){
.root = d,
- .pos = (off_t)(pos - d->data),
- .at = pos,
- .len = line_end - pos,
+ .pos = (off_t)(line_start - d->data),
+ .at = line_start,
+ .len = line_end - line_start,
.hash = hash,
};
/* Starting point for next line: */
pos = line_end;
}
+ sigaction(SIGBUS, &oact, NULL);
/* File are considered binary if they contain embedded '\0' bytes. */
if (embedded_nul)