diff options
| author | 2011-09-18 07:25:01 (JST) | |
|---|---|---|
| committer | 2012-01-04 00:16:01 (JST) | |
| commit | e19f7d7180d64c8ba9ca15f5fe164606f0ec88c1 (patch) | |
| tree | 55faa59f4835bec90fa5d94643cf1600d699cdb7 | |
| parent | bebe89d7c11a92bf206bf6e528c51ffa8ecbc0d5 (diff) | |
| download | cgit-e19f7d7180d64c8ba9ca15f5fe164606f0ec88c1.zip cgit-e19f7d7180d64c8ba9ca15f5fe164606f0ec88c1.tar.gz | |
ui-ssdiff: move LCS table away from the stack
Printing deferred line changes for files containing long lines would
cause a segfault.
- limit LCS table size: 128x128.
- move LCS table to global context: avoid allocating/freeing memory
for every deferred line change.
Signed-off-by: Jamie Couture <jamie.couture@gmail.com>
| -rw-r--r-- | ui-ssdiff.c | 33 | ||||
| -rw-r--r-- | ui-ssdiff.h | 12 |
2 files changed, 43 insertions, 2 deletions
diff --git a/ui-ssdiff.c b/ui-ssdiff.c index 2481585..9fb5b11 100644 --- a/ui-ssdiff.c +++ b/ui-ssdiff.c | |||
| @@ -2,10 +2,12 @@ | |||
| 2 | #include "html.h" | 2 | #include "html.h" |
| 3 | #include "ui-shared.h" | 3 | #include "ui-shared.h" |
| 4 | #include "ui-diff.h" | 4 | #include "ui-diff.h" |
| 5 | #include "ui-ssdiff.h" | ||
| 5 | 6 | ||
| 6 | extern int use_ssdiff; | 7 | extern int use_ssdiff; |
| 7 | 8 | ||
| 8 | static int current_old_line, current_new_line; | 9 | static int current_old_line, current_new_line; |
| 10 | static int **L = NULL; | ||
| 9 | 11 | ||
| 10 | struct deferred_lines { | 12 | struct deferred_lines { |
| 11 | int line_no; | 13 | int line_no; |
| @@ -16,16 +18,42 @@ struct deferred_lines { | |||
| 16 | static struct deferred_lines *deferred_old, *deferred_old_last; | 18 | static struct deferred_lines *deferred_old, *deferred_old_last; |
| 17 | static struct deferred_lines *deferred_new, *deferred_new_last; | 19 | static struct deferred_lines *deferred_new, *deferred_new_last; |
| 18 | 20 | ||
| 21 | static void create_or_reset_lcs_table() | ||
| 22 | { | ||
| 23 | int i; | ||
| 24 | |||
| 25 | if (L != NULL) { | ||
| 26 | memset(*L, 0, sizeof(*L) * MAX_SSDIFF_SIZE); | ||
| 27 | return; | ||
| 28 | } | ||
| 29 | |||
| 30 | // xcalloc will die if we ran out of memory; | ||
| 31 | // not very helpful for debugging | ||
| 32 | L = (int**)xcalloc(MAX_SSDIFF_M, sizeof(int *)); | ||
| 33 | *L = (int*)xcalloc(MAX_SSDIFF_SIZE, sizeof(int)); | ||
| 34 | |||
| 35 | for (i = 1; i < MAX_SSDIFF_M; i++) { | ||
| 36 | L[i] = *L + i * MAX_SSDIFF_N; | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 19 | static char *longest_common_subsequence(char *A, char *B) | 40 | static char *longest_common_subsequence(char *A, char *B) |
| 20 | { | 41 | { |
| 21 | int i, j, ri; | 42 | int i, j, ri; |
| 22 | int m = strlen(A); | 43 | int m = strlen(A); |
| 23 | int n = strlen(B); | 44 | int n = strlen(B); |
| 24 | int L[m + 1][n + 1]; | 45 | int tmp1, tmp2, length; |
| 25 | int tmp1, tmp2; | ||
| 26 | int lcs_length; | 46 | int lcs_length; |
| 27 | char *result; | 47 | char *result; |
| 28 | 48 | ||
| 49 | length = (m + 1) * (n + 1); | ||
| 50 | |||
| 51 | // We bail if the lines are too long | ||
| 52 | if (length > MAX_SSDIFF_SIZE) | ||
| 53 | return NULL; | ||
| 54 | |||
| 55 | create_or_reset_lcs_table(); | ||
| 56 | |||
| 29 | for (i = m; i >= 0; i--) { | 57 | for (i = m; i >= 0; i--) { |
| 30 | for (j = n; j >= 0; j--) { | 58 | for (j = n; j >= 0; j--) { |
| 31 | if (A[i] == '\0' || B[j] == '\0') { | 59 | if (A[i] == '\0' || B[j] == '\0') { |
| @@ -59,6 +87,7 @@ static char *longest_common_subsequence(char *A, char *B) | |||
| 59 | j += 1; | 87 | j += 1; |
| 60 | } | 88 | } |
| 61 | } | 89 | } |
| 90 | |||
| 62 | return result; | 91 | return result; |
| 63 | } | 92 | } |
| 64 | 93 | ||
diff --git a/ui-ssdiff.h b/ui-ssdiff.h index 64b4b12..88627e2 100644 --- a/ui-ssdiff.h +++ b/ui-ssdiff.h | |||
| @@ -1,6 +1,18 @@ | |||
| 1 | #ifndef UI_SSDIFF_H | 1 | #ifndef UI_SSDIFF_H |
| 2 | #define UI_SSDIFF_H | 2 | #define UI_SSDIFF_H |
| 3 | 3 | ||
| 4 | /* | ||
| 5 | * ssdiff line limits | ||
| 6 | */ | ||
| 7 | #ifndef MAX_SSDIFF_M | ||
| 8 | #define MAX_SSDIFF_M 128 | ||
| 9 | #endif | ||
| 10 | |||
| 11 | #ifndef MAX_SSDIFF_N | ||
| 12 | #define MAX_SSDIFF_N 128 | ||
| 13 | #endif | ||
| 14 | #define MAX_SSDIFF_SIZE ((MAX_SSDIFF_M) * (MAX_SSDIFF_N)) | ||
| 15 | |||
| 4 | extern void cgit_ssdiff_print_deferred_lines(); | 16 | extern void cgit_ssdiff_print_deferred_lines(); |
| 5 | 17 | ||
| 6 | extern void cgit_ssdiff_line_cb(char *line, int len); | 18 | extern void cgit_ssdiff_line_cb(char *line, int len); |
