2 Commits
Author SHA1 Message Date
Patrick McCarty e0e8bcda58 Release v1.0.4
This release fixes an issue with libbsdiff thread safety. This was a
regression introduced in v1.0.3.

Signed-off-by: Patrick McCarty <patrick.mccarty@intel.com>
2018-06-14 14:50:54 -07:00
Patrick McCarty 2e5b80929c Make revised search algorithm thread safe
In commit 85b1c5345b, I introduced a new "max_len" variable, used by the
search() function to store the maximum match length found in course of
the binary search.

However, I overlooked the fact that the search() function then lost
thread safety, as "max_len" would be shared by all threads of a process
using libbsdiff.

Fix the issue by not using a global variable, instead updating "max_len"
via another pointer, just like the "pos" variable is handled already.

Signed-off-by: Patrick McCarty <patrick.mccarty@intel.com>
2018-06-14 14:46:52 -07:00
2 changed files with 20 additions and 22 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
AC_PREREQ([2.66]) AC_PREREQ([2.66])
AC_INIT([bsdiff], [1.0.3], [patrick.mccarty@intel.com]) AC_INIT([bsdiff], [1.0.4], [patrick.mccarty@intel.com])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_PROG_CC AC_PROG_CC
AC_PROG_CC_STDC AC_PROG_CC_STDC
+19 -21
View File
@@ -88,24 +88,23 @@ static int64_t matchlen(u_char *old, int64_t oldsize, u_char *new,
return i; return i;
} }
int64_t max_len = 0;
/** /**
* Finds the longest matching array of bytes between the OLD and NEW file. The * Finds the longest matching array of bytes between the OLD and NEW file. The
* old file is suffix-sorted; the suffix-sorted array is stored at I, and * old file is suffix-sorted; the suffix-sorted array is stored at I, and
* indices to search between are indicated by ST (start) and EN (end). Returns * indices to search between are indicated by ST (start) and EN (end). The
* the length of the match, and POS is updated to the position of the match * function does not return a value, but once a match is determined, POS is
* within OLD. * updated to the position of the match within OLD, and MAX_LEN is set to the
* match length.
*/ */
static int64_t search(int64_t *I, u_char *old, int64_t oldsize, static void search(int64_t *I, u_char *old, int64_t oldsize,
u_char *new, int64_t newsize, int64_t st, int64_t en, u_char *new, int64_t newsize, int64_t st, int64_t en,
int64_t *pos) int64_t *pos, int64_t *max_len)
{ {
int64_t x, y; int64_t x, y;
/* Initialize max_len for the binary search */ /* Initialize max_len for the binary search */
if (st == 0 && en == oldsize) { if (st == 0 && en == oldsize) {
max_len = matchlen(old, oldsize, new, newsize); *max_len = matchlen(old, oldsize, new, newsize);
*pos = I[st]; *pos = I[st];
} }
@@ -113,17 +112,17 @@ static int64_t search(int64_t *I, u_char *old, int64_t oldsize,
* indices in the suffix-sorted array. */ * indices in the suffix-sorted array. */
if (en - st < 2) { if (en - st < 2) {
x = matchlen(old + I[st], oldsize - I[st], new, newsize); x = matchlen(old + I[st], oldsize - I[st], new, newsize);
if (x > max_len) { if (x > *max_len) {
max_len = x; *max_len = x;
*pos = I[st]; *pos = I[st];
} }
y = matchlen(old + I[en], oldsize - I[en], new, newsize); y = matchlen(old + I[en], oldsize - I[en], new, newsize);
if (y > max_len) { if (y > *max_len) {
max_len = y; *max_len = y;
*pos = I[en]; *pos = I[en];
} }
return max_len; return;
} }
x = st + (en - st) / 2; x = st + (en - st) / 2;
@@ -133,16 +132,16 @@ static int64_t search(int64_t *I, u_char *old, int64_t oldsize,
/* This match *could* be the longest one, so check for that here */ /* This match *could* be the longest one, so check for that here */
int64_t tmp = matchlen(oldoffset, length, new, length); int64_t tmp = matchlen(oldoffset, length, new, length);
if (tmp > max_len) { if (tmp > *max_len) {
max_len = tmp; *max_len = tmp;
*pos = I[x]; *pos = I[x];
} }
/* Determine how to continue the binary search */ /* Determine how to continue the binary search */
if (memcmp(oldoffset, new, length) < 0) { if (memcmp(oldoffset, new, length) < 0) {
return search(I, old, oldsize, new, newsize, x, en, pos); return search(I, old, oldsize, new, newsize, x, en, pos, max_len);
} else { } else {
return search(I, old, oldsize, new, newsize, st, x, pos); return search(I, old, oldsize, new, newsize, st, x, pos, max_len);
} }
} }
@@ -617,9 +616,8 @@ int make_bsdiff_delta(char *old_filename, char *new_filename, char *delta_filena
oldscore = 0; oldscore = 0;
for (scsc = scan += len; scan < newsize; scan++) { for (scsc = scan += len; scan < newsize; scan++) {
len = search(I, old_data, oldsize, new_data + scan, newsize - scan,
search(I, old_data, oldsize, new_data + scan, newsize - scan, 0, oldsize, &pos, &len);
0, oldsize, &pos);
for (; scsc < scan + len; scsc++) { for (; scsc < scan + len; scsc++) {
if ((scsc + lastoffset < oldsize) && if ((scsc + lastoffset < oldsize) &&