From 9084674ac6b87e36a4171dca2d7ef5c5c6917e25 Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Fri, 4 Dec 2020 13:52:22 +0100 Subject: [PATCH 1/2] dev-util/bsdiff: sync with Gentoo Before applying Flatcar patches to bsdiff, sync with upstream Gentoo, so the ebuilds could make use of EAPI=7. Also drop third-party patches, to be able to start from scratch. Doing that we can fix [CVE-2014-9862](https://nvd.nist.gov/vuln/detail/CVE-2014-9862), integer signedness error in bspatch.c. With the vulnerability, remote attackers to execute arbitrary code or cause a denial of service (heap-based buffer overflow) via a crafted patch file. Since Gentoo already has the third-party patch, we can simply make use of it. See also https://bugs.gentoo.org/701848 , https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=f4d7646f1d69 . --- .../dev-util/bsdiff/bsdiff-4.3-r6.ebuild | 41 - .../dev-util/bsdiff/bsdiff-4.3-r7.ebuild | 35 + ...iff-convert-to-sais-lite-suffix-sort.patch | 754 ------------------ ...tch-support-input-output-positioning.patch | 343 -------- .../files/bsdiff-4.3-CVE-2014-9862.patch | 15 + 5 files changed, 50 insertions(+), 1138 deletions(-) delete mode 100644 sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r6.ebuild create mode 100644 sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r7.ebuild delete mode 100644 sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch delete mode 100644 sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bspatch-support-input-output-positioning.patch create mode 100644 sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/bsdiff-4.3-CVE-2014-9862.patch diff --git a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r6.ebuild b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r6.ebuild deleted file mode 100644 index 2418efc22c..0000000000 --- a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r6.ebuild +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 1999-2010 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/dev-util/bsdiff/bsdiff-4.3-r2.ebuild,v 1.1 2010/12/13 00:35:03 flameeyes Exp $ - -EAPI=2 - -inherit eutils toolchain-funcs flag-o-matic - -IUSE="" - -DESCRIPTION="bsdiff: Binary Differencer using a suffix alg" -HOMEPAGE="http://www.daemonology.net/bsdiff/" -SRC_URI="http://www.daemonology.net/bsdiff/${P}.tar.gz" - -SLOT="0" -LICENSE="BSD-2" -KEYWORDS="alpha amd64 arm arm64 hppa ia64 mips ppc sparc x86 ~x86-fbsd ~x86-freebsd ~amd64-linux ~x86-linux ~ppc-macos" - -RDEPEND="app-arch/bzip2" -DEPEND="${RDEPEND}" - -src_prepare() { - epatch ${FILESDIR}/4.3_bspatch-support-input-output-positioning.patch || die - epatch ${FILESDIR}/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch || die -} - -doecho() { - echo "$@" - "$@" -} - -src_compile() { - append-lfs-flags - doecho $(tc-getCC) ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o bsdiff bsdiff.c sais.c -lbz2 || die "failed compiling bsdiff" - doecho $(tc-getCC) ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o bspatch bspatch.c -lbz2 || die "failed compiling bspatch" -} - -src_install() { - dobin bs{diff,patch} || die - doman bs{diff,patch}.1 || die -} diff --git a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r7.ebuild b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r7.ebuild new file mode 100644 index 0000000000..7fe7308f9e --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r7.ebuild @@ -0,0 +1,35 @@ +# Copyright 1999-2020 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 + +inherit flag-o-matic toolchain-funcs + +DESCRIPTION="bsdiff: Binary Differencer using a suffix alg" +HOMEPAGE="https://www.daemonology.net/bsdiff/" +SRC_URI="https://www.daemonology.net/bsdiff/${P}.tar.gz" + +SLOT="0" +LICENSE="BSD-2" +KEYWORDS="~alpha amd64 ~arm hppa arm64 ~ia64 ~mips ppc sparc x86 ~amd64-linux ~x86-linux ~ppc-macos" + +RDEPEND="app-arch/bzip2" + +PATCHES=( + "${FILESDIR}/${P}-CVE-2014-9862.patch" +) + +src_compile() { + doecho() { + echo "$@" + "$@" + } + append-lfs-flags + doecho $(tc-getCC) ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o bsdiff bsdiff.c -lbz2 || die "failed compiling bsdiff" + doecho $(tc-getCC) ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o bspatch bspatch.c -lbz2 || die "failed compiling bspatch" +} + +src_install() { + dobin bs{diff,patch} + doman bs{diff,patch}.1 +} diff --git a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch deleted file mode 100644 index 589ecad248..0000000000 --- a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch +++ /dev/null @@ -1,754 +0,0 @@ -From f220517e188924e67040c6171ca7e0dede16c6b4 Mon Sep 17 00:00:00 2001 -From: Geoff Levand -Date: Tue, 14 Jul 2015 14:29:21 -0700 -Subject: [PATCH 2/2] bsdiff: Convert to sais-lite suffix sort - -Convert the bsdiff suffix sort algorithm from its own qsufsort implementation to -the sais-lite suffix sort algorithm from [1]. Fixes problems with slow -operation and program hangs as reported in [2] through [4]. - - [1] https://sites.google.com/site/yuta256/sais - [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=409664 - [3] https://github.com/sparkle-project/Sparkle/pull/515 - [4] https://chromium.googlesource.com/chromiumos/third_party/bsdiff/+/e2b85ce4ea246ca804ee2a9e18005c44e193d868 - -Signed-off-by: Geoff Levand ---- - bsdiff.c | 104 +------------ - sais.c | 534 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - sais.h | 59 +++++++ - 3 files changed, 597 insertions(+), 100 deletions(-) - create mode 100644 sais.c - create mode 100644 sais.h - -diff --git a/bsdiff.c b/bsdiff.c -index 150a7f7..5c6c94f 100644 ---- a/bsdiff.c -+++ b/bsdiff.c -@@ -38,106 +38,9 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c,v 1.1 2005/08/06 01:59:05 - #include - #include - --#define MIN(x,y) (((x)<(y)) ? (x) : (y)) -- --static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h) --{ -- off_t i,j,k,x,tmp,jj,kk; -- -- if(len<16) { -- for(k=start;kstart) split(I,V,start,jj-start,h); -- -- for(i=0;ikk) split(I,V,kk,start+len-kk,h); --} -+#include "sais.h" - --static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize) --{ -- off_t buckets[256]; -- off_t i,h,len; -- -- for(i=0;i<256;i++) buckets[i]=0; -- for(i=0;i0;i--) buckets[i]=buckets[i-1]; -- buckets[0]=0; -- -- for(i=0;i -+#include -+#include "sais.h" -+ -+#ifndef UCHAR_SIZE -+# define UCHAR_SIZE 256 -+#endif -+#ifndef MINBUCKETSIZE -+# define MINBUCKETSIZE 256 -+#endif -+ -+#define sais_bool_type int -+#define SAIS_LMSSORT2_LIMIT 0x3fffffff -+ -+#define SAIS_MYMALLOC(_num, _type) ((_type *)malloc((_num) * sizeof(_type))) -+#define SAIS_MYFREE(_ptr, _num, _type) free((_ptr)) -+#define chr(_a) (cs == sizeof(sais_index_type) ? ((sais_index_type *)T)[(_a)] : ((unsigned char *)T)[(_a)]) -+ -+/* find the start or end of each bucket */ -+static -+void -+getCounts(const void *T, sais_index_type *C, sais_index_type n, sais_index_type k, int cs) { -+ sais_index_type i; -+ for(i = 0; i < k; ++i) { C[i] = 0; } -+ for(i = 0; i < n; ++i) { ++C[chr(i)]; } -+} -+static -+void -+getBuckets(const sais_index_type *C, sais_index_type *B, sais_index_type k, sais_bool_type end) { -+ sais_index_type i, sum = 0; -+ if(end) { for(i = 0; i < k; ++i) { sum += C[i]; B[i] = sum; } } -+ else { for(i = 0; i < k; ++i) { sum += C[i]; B[i] = sum - C[i]; } } -+} -+ -+/* sort all type LMS suffixes */ -+static -+void -+LMSsort1(const void *T, sais_index_type *SA, -+ sais_index_type *C, sais_index_type *B, -+ sais_index_type n, sais_index_type k, int cs) { -+ sais_index_type *b, i, j; -+ sais_index_type c0, c1; -+ -+ /* compute SAl */ -+ if(C == B) { getCounts(T, C, n, k, cs); } -+ getBuckets(C, B, k, 0); /* find starts of buckets */ -+ j = n - 1; -+ b = SA + B[c1 = chr(j)]; -+ --j; -+ *b++ = (chr(j) < c1) ? ~j : j; -+ for(i = 0; i < n; ++i) { -+ if(0 < (j = SA[i])) { -+ assert(chr(j) >= chr(j + 1)); -+ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } -+ assert(i < (b - SA)); -+ --j; -+ *b++ = (chr(j) < c1) ? ~j : j; -+ SA[i] = 0; -+ } else if(j < 0) { -+ SA[i] = ~j; -+ } -+ } -+ /* compute SAs */ -+ if(C == B) { getCounts(T, C, n, k, cs); } -+ getBuckets(C, B, k, 1); /* find ends of buckets */ -+ for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) { -+ if(0 < (j = SA[i])) { -+ assert(chr(j) <= chr(j + 1)); -+ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } -+ assert((b - SA) <= i); -+ --j; -+ *--b = (chr(j) > c1) ? ~(j + 1) : j; -+ SA[i] = 0; -+ } -+ } -+} -+static -+sais_index_type -+LMSpostproc1(const void *T, sais_index_type *SA, -+ sais_index_type n, sais_index_type m, int cs) { -+ sais_index_type i, j, p, q, plen, qlen, name; -+ sais_index_type c0, c1; -+ sais_bool_type diff; -+ -+ /* compact all the sorted substrings into the first m items of SA -+ 2*m must be not larger than n (proveable) */ -+ assert(0 < n); -+ for(i = 0; (p = SA[i]) < 0; ++i) { SA[i] = ~p; assert((i + 1) < n); } -+ if(i < m) { -+ for(j = i, ++i;; ++i) { -+ assert(i < n); -+ if((p = SA[i]) < 0) { -+ SA[j++] = ~p; SA[i] = 0; -+ if(j == m) { break; } -+ } -+ } -+ } -+ -+ /* store the length of all substrings */ -+ i = n - 1; j = n - 1; c0 = chr(n - 1); -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); -+ for(; 0 <= i;) { -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1)); -+ if(0 <= i) { -+ SA[m + ((i + 1) >> 1)] = j - i; j = i + 1; -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); -+ } -+ } -+ -+ /* find the lexicographic names of all substrings */ -+ for(i = 0, name = 0, q = n, qlen = 0; i < m; ++i) { -+ p = SA[i], plen = SA[m + (p >> 1)], diff = 1; -+ if((plen == qlen) && ((q + plen) < n)) { -+ for(j = 0; (j < plen) && (chr(p + j) == chr(q + j)); ++j) { } -+ if(j == plen) { diff = 0; } -+ } -+ if(diff != 0) { ++name, q = p, qlen = plen; } -+ SA[m + (p >> 1)] = name; -+ } -+ -+ return name; -+} -+static -+void -+LMSsort2(const void *T, sais_index_type *SA, -+ sais_index_type *C, sais_index_type *B, sais_index_type *D, -+ sais_index_type n, sais_index_type k, int cs) { -+ sais_index_type *b, i, j, t, d; -+ sais_index_type c0, c1; -+ assert(C != B); -+ -+ /* compute SAl */ -+ getBuckets(C, B, k, 0); /* find starts of buckets */ -+ j = n - 1; -+ b = SA + B[c1 = chr(j)]; -+ --j; -+ t = (chr(j) < c1); -+ j += n; -+ *b++ = (t & 1) ? ~j : j; -+ for(i = 0, d = 0; i < n; ++i) { -+ if(0 < (j = SA[i])) { -+ if(n <= j) { d += 1; j -= n; } -+ assert(chr(j) >= chr(j + 1)); -+ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } -+ assert(i < (b - SA)); -+ --j; -+ t = c0; t = (t << 1) | (chr(j) < c1); -+ if(D[t] != d) { j += n; D[t] = d; } -+ *b++ = (t & 1) ? ~j : j; -+ SA[i] = 0; -+ } else if(j < 0) { -+ SA[i] = ~j; -+ } -+ } -+ for(i = n - 1; 0 <= i; --i) { -+ if(0 < SA[i]) { -+ if(SA[i] < n) { -+ SA[i] += n; -+ for(j = i - 1; SA[j] < n; --j) { } -+ SA[j] -= n; -+ i = j; -+ } -+ } -+ } -+ -+ /* compute SAs */ -+ getBuckets(C, B, k, 1); /* find ends of buckets */ -+ for(i = n - 1, d += 1, b = SA + B[c1 = 0]; 0 <= i; --i) { -+ if(0 < (j = SA[i])) { -+ if(n <= j) { d += 1; j -= n; } -+ assert(chr(j) <= chr(j + 1)); -+ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } -+ assert((b - SA) <= i); -+ --j; -+ t = c0; t = (t << 1) | (chr(j) > c1); -+ if(D[t] != d) { j += n; D[t] = d; } -+ *--b = (t & 1) ? ~(j + 1) : j; -+ SA[i] = 0; -+ } -+ } -+} -+static -+sais_index_type -+LMSpostproc2(sais_index_type *SA, sais_index_type n, sais_index_type m) { -+ sais_index_type i, j, d, name; -+ -+ /* compact all the sorted LMS substrings into the first m items of SA */ -+ assert(0 < n); -+ for(i = 0, name = 0; (j = SA[i]) < 0; ++i) { -+ j = ~j; -+ if(n <= j) { name += 1; } -+ SA[i] = j; -+ assert((i + 1) < n); -+ } -+ if(i < m) { -+ for(d = i, ++i;; ++i) { -+ assert(i < n); -+ if((j = SA[i]) < 0) { -+ j = ~j; -+ if(n <= j) { name += 1; } -+ SA[d++] = j; SA[i] = 0; -+ if(d == m) { break; } -+ } -+ } -+ } -+ if(name < m) { -+ /* store the lexicographic names */ -+ for(i = m - 1, d = name + 1; 0 <= i; --i) { -+ if(n <= (j = SA[i])) { j -= n; --d; } -+ SA[m + (j >> 1)] = d; -+ } -+ } else { -+ /* unset flags */ -+ for(i = 0; i < m; ++i) { -+ if(n <= (j = SA[i])) { j -= n; SA[i] = j; } -+ } -+ } -+ -+ return name; -+} -+ -+/* compute SA and BWT */ -+static -+void -+induceSA(const void *T, sais_index_type *SA, -+ sais_index_type *C, sais_index_type *B, -+ sais_index_type n, sais_index_type k, int cs) { -+ sais_index_type *b, i, j; -+ sais_index_type c0, c1; -+ /* compute SAl */ -+ if(C == B) { getCounts(T, C, n, k, cs); } -+ getBuckets(C, B, k, 0); /* find starts of buckets */ -+ j = n - 1; -+ b = SA + B[c1 = chr(j)]; -+ *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j; -+ for(i = 0; i < n; ++i) { -+ j = SA[i], SA[i] = ~j; -+ if(0 < j) { -+ --j; -+ assert(chr(j) >= chr(j + 1)); -+ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } -+ assert(i < (b - SA)); -+ *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j; -+ } -+ } -+ /* compute SAs */ -+ if(C == B) { getCounts(T, C, n, k, cs); } -+ getBuckets(C, B, k, 1); /* find ends of buckets */ -+ for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) { -+ if(0 < (j = SA[i])) { -+ --j; -+ assert(chr(j) <= chr(j + 1)); -+ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } -+ assert((b - SA) <= i); -+ *--b = ((j == 0) || (chr(j - 1) > c1)) ? ~j : j; -+ } else { -+ SA[i] = ~j; -+ } -+ } -+} -+static -+sais_index_type -+computeBWT(const void *T, sais_index_type *SA, -+ sais_index_type *C, sais_index_type *B, -+ sais_index_type n, sais_index_type k, int cs) { -+ sais_index_type *b, i, j, pidx = -1; -+ sais_index_type c0, c1; -+ /* compute SAl */ -+ if(C == B) { getCounts(T, C, n, k, cs); } -+ getBuckets(C, B, k, 0); /* find starts of buckets */ -+ j = n - 1; -+ b = SA + B[c1 = chr(j)]; -+ *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j; -+ for(i = 0; i < n; ++i) { -+ if(0 < (j = SA[i])) { -+ --j; -+ assert(chr(j) >= chr(j + 1)); -+ SA[i] = ~((sais_index_type)(c0 = chr(j))); -+ if(c0 != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } -+ assert(i < (b - SA)); -+ *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j; -+ } else if(j != 0) { -+ SA[i] = ~j; -+ } -+ } -+ /* compute SAs */ -+ if(C == B) { getCounts(T, C, n, k, cs); } -+ getBuckets(C, B, k, 1); /* find ends of buckets */ -+ for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) { -+ if(0 < (j = SA[i])) { -+ --j; -+ assert(chr(j) <= chr(j + 1)); -+ SA[i] = (c0 = chr(j)); -+ if(c0 != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } -+ assert((b - SA) <= i); -+ *--b = ((0 < j) && (chr(j - 1) > c1)) ? ~((sais_index_type)chr(j - 1)) : j; -+ } else if(j != 0) { -+ SA[i] = ~j; -+ } else { -+ pidx = i; -+ } -+ } -+ return pidx; -+} -+ -+/* find the suffix array SA of T[0..n-1] in {0..255}^n */ -+static -+sais_index_type -+sais_main(const void *T, sais_index_type *SA, -+ sais_index_type fs, sais_index_type n, sais_index_type k, int cs, -+ sais_bool_type isbwt) { -+ sais_index_type *C, *B, *D, *RA, *b; -+ sais_index_type i, j, m, p, q, t, name, pidx = 0, newfs; -+ sais_index_type c0, c1; -+ unsigned int flags; -+ -+ assert((T != NULL) && (SA != NULL)); -+ assert((0 <= fs) && (0 < n) && (1 <= k)); -+ -+ if(k <= MINBUCKETSIZE) { -+ if((C = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { return -2; } -+ if(k <= fs) { -+ B = SA + (n + fs - k); -+ flags = 1; -+ } else { -+ if((B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { SAIS_MYFREE(C, k, sais_index_type); return -2; } -+ flags = 3; -+ } -+ } else if(k <= fs) { -+ C = SA + (n + fs - k); -+ if(k <= (fs - k)) { -+ B = C - k; -+ flags = 0; -+ } else if(k <= (MINBUCKETSIZE * 4)) { -+ if((B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { return -2; } -+ flags = 2; -+ } else { -+ B = C; -+ flags = 8; -+ } -+ } else { -+ if((C = B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { return -2; } -+ flags = 4 | 8; -+ } -+ if((n <= SAIS_LMSSORT2_LIMIT) && (2 <= (n / k))) { -+ if(flags & 1) { flags |= ((k * 2) <= (fs - k)) ? 32 : 16; } -+ else if((flags == 0) && ((k * 2) <= (fs - k * 2))) { flags |= 32; } -+ } -+ -+ /* stage 1: reduce the problem by at least 1/2 -+ sort all the LMS-substrings */ -+ getCounts(T, C, n, k, cs); getBuckets(C, B, k, 1); /* find ends of buckets */ -+ for(i = 0; i < n; ++i) { SA[i] = 0; } -+ b = &t; i = n - 1; j = n; m = 0; c0 = chr(n - 1); -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); -+ for(; 0 <= i;) { -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1)); -+ if(0 <= i) { -+ *b = j; b = SA + --B[c1]; j = i; ++m; -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); -+ } -+ } -+ -+ if(1 < m) { -+ if(flags & (16 | 32)) { -+ if(flags & 16) { -+ if((D = SAIS_MYMALLOC((size_t)k * 2, sais_index_type)) == NULL) { -+ if(flags & (1 | 4)) { SAIS_MYFREE(C, k, sais_index_type); } -+ if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); } -+ return -2; -+ } -+ } else { -+ D = B - k * 2; -+ } -+ assert((j + 1) < n); -+ ++B[chr(j + 1)]; -+ for(i = 0, j = 0; i < k; ++i) { -+ j += C[i]; -+ if(B[i] != j) { assert(SA[B[i]] != 0); SA[B[i]] += n; } -+ D[i] = D[i + k] = 0; -+ } -+ LMSsort2(T, SA, C, B, D, n, k, cs); -+ name = LMSpostproc2(SA, n, m); -+ if(flags & 16) { SAIS_MYFREE(D, k * 2, sais_index_type); } -+ } else { -+ LMSsort1(T, SA, C, B, n, k, cs); -+ name = LMSpostproc1(T, SA, n, m, cs); -+ } -+ } else if(m == 1) { -+ *b = j + 1; -+ name = 1; -+ } else { -+ name = 0; -+ } -+ -+ /* stage 2: solve the reduced problem -+ recurse if names are not yet unique */ -+ if(name < m) { -+ if(flags & 4) { SAIS_MYFREE(C, k, sais_index_type); } -+ if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); } -+ newfs = (n + fs) - (m * 2); -+ if((flags & (1 | 4 | 8)) == 0) { -+ if((k + name) <= newfs) { newfs -= k; } -+ else { flags |= 8; } -+ } -+ assert((n >> 1) <= (newfs + m)); -+ RA = SA + m + newfs; -+ for(i = m + (n >> 1) - 1, j = m - 1; m <= i; --i) { -+ if(SA[i] != 0) { -+ RA[j--] = SA[i] - 1; -+ } -+ } -+ if(sais_main(RA, SA, newfs, m, name, sizeof(sais_index_type), 0) != 0) { -+ if(flags & 1) { SAIS_MYFREE(C, k, sais_index_type); } -+ return -2; -+ } -+ -+ i = n - 1; j = m - 1; c0 = chr(n - 1); -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); -+ for(; 0 <= i;) { -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1)); -+ if(0 <= i) { -+ RA[j--] = i + 1; -+ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); -+ } -+ } -+ for(i = 0; i < m; ++i) { SA[i] = RA[SA[i]]; } -+ if(flags & 4) { -+ if((C = B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { return -2; } -+ } -+ if(flags & 2) { -+ if((B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { -+ if(flags & 1) { SAIS_MYFREE(C, k, sais_index_type); } -+ return -2; -+ } -+ } -+ } -+ -+ /* stage 3: induce the result for the original problem */ -+ if(flags & 8) { getCounts(T, C, n, k, cs); } -+ /* put all left-most S characters into their buckets */ -+ if(1 < m) { -+ getBuckets(C, B, k, 1); /* find ends of buckets */ -+ i = m - 1, j = n, p = SA[m - 1], c1 = chr(p); -+ do { -+ q = B[c0 = c1]; -+ while(q < j) { SA[--j] = 0; } -+ do { -+ SA[--j] = p; -+ if(--i < 0) { break; } -+ p = SA[i]; -+ } while((c1 = chr(p)) == c0); -+ } while(0 <= i); -+ while(0 < j) { SA[--j] = 0; } -+ } -+ if(isbwt == 0) { induceSA(T, SA, C, B, n, k, cs); } -+ else { pidx = computeBWT(T, SA, C, B, n, k, cs); } -+ if(flags & (1 | 4)) { SAIS_MYFREE(C, k, sais_index_type); } -+ if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); } -+ -+ return pidx; -+} -+ -+/*---------------------------------------------------------------------------*/ -+ -+sais_index_type -+sais(const unsigned char *T, sais_index_type *SA, int n) { -+ if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; } -+ if(n <= 1) { if(n == 1) { SA[0] = 0; } return 0; } -+ return sais_main(T, SA, 0, n, UCHAR_SIZE, sizeof(unsigned char), 0); -+} -+ -+sais_index_type -+sais_int(const int *T, sais_index_type *SA, int n, int k) { -+ if((T == NULL) || (SA == NULL) || (n < 0) || (k <= 0)) { return -1; } -+ if(n <= 1) { if(n == 1) { SA[0] = 0; } return 0; } -+ return sais_main(T, SA, 0, n, k, sizeof(int), 0); -+} -+ -+sais_index_type -+sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n) { -+ int i; -+ sais_index_type pidx; -+ if((T == NULL) || (U == NULL) || (A == NULL) || (n < 0)) { return -1; } -+ if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; } -+ pidx = sais_main(T, A, 0, n, UCHAR_SIZE, sizeof(unsigned char), 1); -+ if(pidx < 0) { return pidx; } -+ U[0] = T[n - 1]; -+ for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)A[i]; } -+ for(i += 1; i < n; ++i) { U[i] = (unsigned char)A[i]; } -+ pidx += 1; -+ return pidx; -+} -+ -+sais_index_type -+sais_int_bwt(const sais_index_type *T, sais_index_type *U, sais_index_type *A, int n, int k) { -+ int i; -+ sais_index_type pidx; -+ if((T == NULL) || (U == NULL) || (A == NULL) || (n < 0) || (k <= 0)) { return -1; } -+ if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; } -+ pidx = sais_main(T, A, 0, n, k, sizeof(int), 1); -+ if(pidx < 0) { return pidx; } -+ U[0] = T[n - 1]; -+ for(i = 0; i < pidx; ++i) { U[i + 1] = A[i]; } -+ for(i += 1; i < n; ++i) { U[i] = A[i]; } -+ pidx += 1; -+ return pidx; -+} -diff --git a/sais.h b/sais.h -new file mode 100644 -index 0000000..1abd0af ---- /dev/null -+++ b/sais.h -@@ -0,0 +1,59 @@ -+/* -+ * sais.h for sais-lite -+ * Copyright (c) 2008-2010 Yuta Mori All Rights Reserved. -+ * -+ * Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef _SAIS_H -+#define _SAIS_H 1 -+ -+#ifdef __cplusplus -+extern "C" { -+#endif /* __cplusplus */ -+ -+#include -+ -+#define sais_index_type off_t -+ -+/* find the suffix array SA of T[0..n-1] -+ use a working space (excluding T and SA) of at most 2n+O(lg n) */ -+sais_index_type -+sais(const unsigned char *T, sais_index_type *SA, int n); -+ -+/* find the suffix array SA of T[0..n-1] in {0..k-1}^n -+ use a working space (excluding T and SA) of at most MAX(4k,2n) */ -+sais_index_type -+sais_int(const int *T, sais_index_type *SA, int n, int k); -+ -+/* burrows-wheeler transform */ -+sais_index_type -+sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n); -+sais_index_type -+sais_int_bwt(const sais_index_type *T, sais_index_type *U, sais_index_type *A, int n, int k); -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif /* __cplusplus */ -+ -+#endif /* _SAIS_H */ --- -2.1.0 - diff --git a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bspatch-support-input-output-positioning.patch b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bspatch-support-input-output-positioning.patch deleted file mode 100644 index 928fa00706..0000000000 --- a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bspatch-support-input-output-positioning.patch +++ /dev/null @@ -1,343 +0,0 @@ ---- bsdiff-4.3/bspatch.c 2005-08-16 15:14:00.000000000 -0700 -+++ bsdiff-4.3-new/bspatch.c 2010-10-12 13:57:08.000000000 -0700 -@@ -3,7 +3,7 @@ - * All rights reserved - * - * Redistribution and use in source and binary forms, with or without -- * modification, are permitted providing that the following conditions -+ * modification, are permitted providing that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. -@@ -29,6 +29,9 @@ - #endif - - #include -+#include -+#include -+#include - #include - #include - #include -@@ -36,6 +39,264 @@ - #include - #include - -+#define JOIN(a, b) __JOIN(a, b) -+#define __JOIN(a, b) a ## b -+#define COMPILE_ASSERT(expr, message) \ -+ typedef char JOIN(message, JOIN(_, __LINE__)) [(expr) ? 1 : -1] -+ -+COMPILE_ASSERT(sizeof(int64_t) == 8, int64_t_64_bit); -+COMPILE_ASSERT(sizeof(off_t) == 8, off_t_64_bit); -+ -+#define MIN(a, b) \ -+ ((a) < (b) ? (a) : (b)) -+ -+static const char kFdFilePrefix[] = "/dev/fd/"; -+ -+// Reads next int from *ints. The int should be terminated with a comma -+// or NULL char. *ints will be updated to the space right after the comma -+// or set to NULL if this was the last number. This assumes the input is -+// a valid string, as validated with PositionsStringIsValid(). -+// Returns 1 on success. -+int NextInt64(const char** ints, int64_t *out) { -+ if (!ints[0]) -+ return 0; -+ int r = sscanf(*ints, "%" PRIi64, out); -+ if (r == 1) { -+ const char* next_comma = strchr(*ints, ','); -+ const char* next_colon = strchr(*ints, ':'); -+ if (!next_comma && !next_colon) -+ *ints = NULL; -+ else if (!next_comma) -+ *ints = next_colon + 1; -+ else if (!next_colon) -+ *ints = next_comma + 1; -+ else -+ *ints = MIN(next_comma, next_colon) + 1; -+ return 1; -+ } -+ return 0; -+} -+ -+COMPILE_ASSERT(sizeof(intmax_t) == 8, intmax_t_not_64_bit); -+ -+// Returns 1 if str can be converted to int64_t without over/underflowing. -+// str is assumed to point to an optional negative sign followed by numbers, -+// optionally followed by non-numeric characters, followed by '\0'. -+int IsValidInt64(const char* str) { -+ char* end_ptr = 0; -+ errno = 0; -+ intmax_t result = strtoimax(str, &end_ptr, /* base: */ 10); -+ return errno == 0; -+} -+ -+// Input validator. Make sure the positions string is well formatted. -+// All numerical values are checked to make sure they don't over/underflow -+// int64_t. Returns 1 if valid. -+int PositionsStringIsValid(const char* positions) { -+ if (positions == NULL) -+ errx(1, "bad string"); -+ -+ // Special case: empty string is valid -+ if (!positions[0]) -+ return 1; -+ -+ // Use a state machine to determine if the string is valid. -+ // Key: (s): state, ((s)) valid end state. -+ // n (negative_valid) is a boolean that starts out as true. -+ // If n is true, ':' is the delimiter, otherwise ','. -+ // -+ // .--------------------------. -+ // | | n ? ':' : ',' ; n = !n -+ // V '-'&&n 0-9 | -+ // start->(0)------------->(1)----->((2))---. -+ // `---------------------> <--' 0-9 -+ // 0-9 -+ int state = 0; -+ int negative_valid = 1; -+ const char* number_start = positions; -+ for (;; positions++) { -+ char c = *positions; -+ switch (state) { -+ case 0: -+ if (c == '-' && negative_valid) { -+ state = 1; -+ continue; -+ } -+ if (isdigit(c)) { -+ state = 2; -+ continue; -+ } -+ return 0; -+ case 1: -+ if (isdigit(c)) { -+ state = 2; -+ continue; -+ } -+ return 0; -+ case 2: -+ if (isdigit(c)) -+ continue; -+ // number_start must point to a valid number -+ if (!IsValidInt64(number_start)) { -+ return 0; -+ } -+ if ((negative_valid && c == ':') || -+ (!negative_valid && c == ',')) { -+ state = 0; -+ number_start = positions + 1; -+ negative_valid = !negative_valid; -+ continue; -+ } -+ return (c == '\0'); -+ } -+ } -+} -+ -+static const int64_t kMaxLength = sizeof(size_t) > 4 ? INT64_MAX : SIZE_MAX; -+ -+// Reads into a buffer a series of byte ranges from filename. -+// Each range is a pair of comma-separated ints from positions. -+// -1 as an offset means a sparse-hole. -+// E.g. If positions were "1,5:23,4:-1,8:3,7", then we would return a buffer -+// consisting of 5 bytes from offset 1 of the file, followed by -+// 4 bytes from offset 23, then 8 bytes of all zeros, then 7 bytes from -+// offset 3 in the file. -+// Returns NULL on error. -+static char* PositionedRead(const char* filename, -+ const char* positions, -+ ssize_t* old_size) { -+ if (!PositionsStringIsValid(positions)) { -+ errx(1, "invalid positions string for read\n"); -+ } -+ -+ // Get length -+ const char* p = positions; -+ int64_t length = 0; -+ for (;;) { -+ int64_t value; -+ if (0 == NextInt64(&p, &value)) { -+ break; -+ } -+ int r = NextInt64(&p, &value); -+ if (r == 0) { -+ errx(1, "bad length parse\n"); -+ } -+ if (value < 0) { -+ errx(1, "length can't be negative\n"); -+ } -+ length += value; -+ } -+ -+ // Malloc -+ if (length > 0x40000000) { // 1 GiB; sanity check -+ errx(1, "Read length too long (exceeds 1 GiB)"); -+ } -+ // Following bsdiff convention, allocate length + 1 to avoid malloc(0) -+ char* buf = malloc(length + 1); -+ if (buf == NULL) { -+ errx(1, "malloc failed\n"); -+ } -+ char* buf_tail = buf; -+ -+ int fd = -1; -+ int should_close = 1; -+ if (strlen(filename) > strlen(kFdFilePrefix) && -+ !strncmp(filename, kFdFilePrefix, strlen(kFdFilePrefix))) { -+ sscanf(filename + strlen(kFdFilePrefix), "%d", &fd); -+ should_close = 0; -+ } else { -+ fd = open(filename, O_RDONLY); -+ } -+ if (fd < 0) { -+ errx(1, "open failed for read\n"); -+ } -+ -+ // Read bytes -+ p = positions; -+ for (;;) { -+ int64_t offset, read_length; -+ if (NextInt64(&p, &offset) == 0) { -+ break; -+ } -+ if (offset < 0) { -+ errx(1, "no support for sparse positions " -+ "yet during read\n"); -+ } -+ if (NextInt64(&p, &read_length) == 0) { -+ errx(1, "bad length parse (should never happen)\n"); -+ } -+ if (read_length < 0) { -+ errx(1, "length can't be negative " -+ "(should never happen)\n"); -+ } -+ if (read_length > kMaxLength) { -+ errx(1, "read length too large\n"); -+ } -+ ssize_t rc = pread(fd, buf_tail, (size_t)read_length, (off_t)offset); -+ if (rc != read_length) { -+ errx(1, "read failed\n"); -+ } -+ buf_tail += rc; -+ } -+ if (should_close) -+ close(fd); -+ *old_size = length; -+ return buf; -+} -+ -+static void PositionedWrite(const char* filename, -+ const char* positions, -+ const char* buf, -+ ssize_t new_size) { -+ if (!PositionsStringIsValid(positions)) { -+ errx(1, "invalid positions string for write\n"); -+ } -+ int fd = -1; -+ int should_close = 1; -+ if (strlen(filename) > strlen(kFdFilePrefix) && -+ !strncmp(filename, kFdFilePrefix, strlen(kFdFilePrefix))) { -+ sscanf(filename + strlen(kFdFilePrefix), "%d", &fd); -+ should_close = 0; -+ } else { -+ fd = open(filename, O_WRONLY | O_CREAT, 0666); -+ } -+ if (fd < 0) { -+ errx(1, "open failed for write\n"); -+ } -+ -+ for (;;) { -+ int64_t offset, length; -+ if (NextInt64(&positions, &offset) == 0) { -+ break; -+ } -+ if (NextInt64(&positions, &length) == 0) { -+ errx(1, "bad length parse for write\n"); -+ } -+ if (length < 0) { -+ errx(1, "length can't be negative for write\n"); -+ } -+ if (length > kMaxLength) { -+ errx(1, "write length too large\n"); -+ } -+ -+ if (offset < 0) { -+ // Sparse hole. Skip. -+ } else { -+ ssize_t rc = pwrite(fd, buf, (size_t)length, (off_t)offset); -+ if (rc != length) { -+ errx(1, "write failed\n"); -+ } -+ } -+ buf += length; -+ new_size -= length; -+ } -+ if (new_size != 0) { -+ errx(1, "output position length doesn't match new size\n"); -+ } -+ if (should_close) -+ close(fd); -+} -+ - static off_t offtin(u_char *buf) - { - off_t y; -@@ -69,7 +330,13 @@ - off_t lenread; - off_t i; - -- if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]); -+ if ((argc != 6) && (argc != 4)) { -+ errx(1,"usage: %s oldfile newfile patchfile \\\n" -+ " [in_offset,in_length,in_offset,in_length,... \\\n" -+ " out_offset,out_length," -+ "out_offset,out_length,...]\n",argv[0]); -+ } -+ int using_positioning = (argc == 6); - - /* Open patch file */ - if ((f = fopen(argv[3], "r")) == NULL) -@@ -132,12 +399,18 @@ - if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL) - errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err); - -- if(((fd=open(argv[1],O_RDONLY,0))<0) || -- ((oldsize=lseek(fd,0,SEEK_END))==-1) || -- ((old=malloc(oldsize+1))==NULL) || -- (lseek(fd,0,SEEK_SET)!=0) || -- (read(fd,old,oldsize)!=oldsize) || -- (close(fd)==-1)) err(1,"%s",argv[1]); -+ // Read -+ -+ if (!using_positioning) { -+ if(((fd=open(argv[1],O_RDONLY,0))<0) || -+ ((oldsize=lseek(fd,0,SEEK_END))==-1) || -+ ((old=malloc(oldsize+1))==NULL) || -+ (lseek(fd,0,SEEK_SET)!=0) || -+ (read(fd,old,oldsize)!=oldsize) || -+ (close(fd)==-1)) err(1,"%s",argv[1]); -+ } else { -+ old = PositionedRead(argv[1], argv[4], &oldsize); -+ } - if((new=malloc(newsize+1))==NULL) err(1,NULL); - - oldpos=0;newpos=0; -@@ -193,9 +466,13 @@ - err(1, "fclose(%s)", argv[3]); - - /* Write the new file */ -- if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || -- (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) -- err(1,"%s",argv[2]); -+ if (!using_positioning) { -+ if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY,0666))<0) || -+ (write(fd,new,newsize)!=newsize) || (close(fd)==-1)) -+ err(1,"%s",argv[2]); -+ } else { -+ PositionedWrite(argv[2], argv[5], new, newsize); -+ } - - free(new); - free(old); diff --git a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/bsdiff-4.3-CVE-2014-9862.patch b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/bsdiff-4.3-CVE-2014-9862.patch new file mode 100644 index 0000000000..7aab818090 --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/bsdiff-4.3-CVE-2014-9862.patch @@ -0,0 +1,15 @@ +diff --git a/bspatch.c b/bspatch.c +index 8d95633..ab77722 100644 +--- a/bspatch.c ++++ b/bspatch.c + +@@ -187,6 +187,10 @@ + }; + + /* Sanity-check */ ++ if ((ctrl[0] < 0) || (ctrl[1] < 0)) ++ errx(1,"Corrupt patch\n"); ++ ++ /* Sanity-check */ + if(newpos+ctrl[0]>newsize) + errx(1,"Corrupt patch\n"); From 50bfd50100da34ba79b240d9490b14721412d9e5 Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Fri, 4 Dec 2020 13:53:24 +0100 Subject: [PATCH 2/2] dev-util/bsdiff: apply Flatcar changes Apply existing Flatcar changes on top of vanilla Gentoo ebuilds. Basically add arm64 keyword, and apply the sais patch. It is based on the following commits: [4ee6aa895a02](https://github.com/kinvolk/coreos-overlay/commit/4ee6aa895a02) ("Add arm64 keywords") [60d47e7359d1](https://github.com/kinvolk/coreos-overlay/commit/60d47e7359d1) ("Change suffix sort to sais-lite") --- .../dev-util/bsdiff/bsdiff-4.3-r7.ebuild | 9 +- ...iff-convert-to-sais-lite-suffix-sort.patch | 754 ++++++++++++++++++ 2 files changed, 761 insertions(+), 2 deletions(-) create mode 100644 sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch diff --git a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r7.ebuild b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r7.ebuild index 7fe7308f9e..1c36fc7add 100644 --- a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r7.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/bsdiff-4.3-r7.ebuild @@ -11,12 +11,15 @@ SRC_URI="https://www.daemonology.net/bsdiff/${P}.tar.gz" SLOT="0" LICENSE="BSD-2" -KEYWORDS="~alpha amd64 ~arm hppa arm64 ~ia64 ~mips ppc sparc x86 ~amd64-linux ~x86-linux ~ppc-macos" +# Flatcar: enable arm64 +KEYWORDS="~alpha amd64 ~arm arm64 hppa arm64 ~ia64 ~mips ppc sparc x86 ~amd64-linux ~x86-linux ~ppc-macos" RDEPEND="app-arch/bzip2" PATCHES=( "${FILESDIR}/${P}-CVE-2014-9862.patch" + # Flatcar: Apply patch to change suffix sort to sais-lite + "${FILESDIR}/${PV}_bsdiff-convert-to-sais-lite-suffix-sort.patch" ) src_compile() { @@ -25,7 +28,9 @@ src_compile() { "$@" } append-lfs-flags - doecho $(tc-getCC) ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o bsdiff bsdiff.c -lbz2 || die "failed compiling bsdiff" + # Flatcar: build including sais.c, which comes from 3rd-party patch + # 4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch. + doecho $(tc-getCC) ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o bsdiff bsdiff.c sais.c -lbz2 || die "failed compiling bsdiff" doecho $(tc-getCC) ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} -o bspatch bspatch.c -lbz2 || die "failed compiling bspatch" } diff --git a/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch new file mode 100644 index 0000000000..589ecad248 --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/dev-util/bsdiff/files/4.3_bsdiff-convert-to-sais-lite-suffix-sort.patch @@ -0,0 +1,754 @@ +From f220517e188924e67040c6171ca7e0dede16c6b4 Mon Sep 17 00:00:00 2001 +From: Geoff Levand +Date: Tue, 14 Jul 2015 14:29:21 -0700 +Subject: [PATCH 2/2] bsdiff: Convert to sais-lite suffix sort + +Convert the bsdiff suffix sort algorithm from its own qsufsort implementation to +the sais-lite suffix sort algorithm from [1]. Fixes problems with slow +operation and program hangs as reported in [2] through [4]. + + [1] https://sites.google.com/site/yuta256/sais + [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=409664 + [3] https://github.com/sparkle-project/Sparkle/pull/515 + [4] https://chromium.googlesource.com/chromiumos/third_party/bsdiff/+/e2b85ce4ea246ca804ee2a9e18005c44e193d868 + +Signed-off-by: Geoff Levand +--- + bsdiff.c | 104 +------------ + sais.c | 534 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + sais.h | 59 +++++++ + 3 files changed, 597 insertions(+), 100 deletions(-) + create mode 100644 sais.c + create mode 100644 sais.h + +diff --git a/bsdiff.c b/bsdiff.c +index 150a7f7..5c6c94f 100644 +--- a/bsdiff.c ++++ b/bsdiff.c +@@ -38,106 +38,9 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bsdiff/bsdiff.c,v 1.1 2005/08/06 01:59:05 + #include + #include + +-#define MIN(x,y) (((x)<(y)) ? (x) : (y)) +- +-static void split(off_t *I,off_t *V,off_t start,off_t len,off_t h) +-{ +- off_t i,j,k,x,tmp,jj,kk; +- +- if(len<16) { +- for(k=start;kstart) split(I,V,start,jj-start,h); +- +- for(i=0;ikk) split(I,V,kk,start+len-kk,h); +-} ++#include "sais.h" + +-static void qsufsort(off_t *I,off_t *V,u_char *old,off_t oldsize) +-{ +- off_t buckets[256]; +- off_t i,h,len; +- +- for(i=0;i<256;i++) buckets[i]=0; +- for(i=0;i0;i--) buckets[i]=buckets[i-1]; +- buckets[0]=0; +- +- for(i=0;i ++#include ++#include "sais.h" ++ ++#ifndef UCHAR_SIZE ++# define UCHAR_SIZE 256 ++#endif ++#ifndef MINBUCKETSIZE ++# define MINBUCKETSIZE 256 ++#endif ++ ++#define sais_bool_type int ++#define SAIS_LMSSORT2_LIMIT 0x3fffffff ++ ++#define SAIS_MYMALLOC(_num, _type) ((_type *)malloc((_num) * sizeof(_type))) ++#define SAIS_MYFREE(_ptr, _num, _type) free((_ptr)) ++#define chr(_a) (cs == sizeof(sais_index_type) ? ((sais_index_type *)T)[(_a)] : ((unsigned char *)T)[(_a)]) ++ ++/* find the start or end of each bucket */ ++static ++void ++getCounts(const void *T, sais_index_type *C, sais_index_type n, sais_index_type k, int cs) { ++ sais_index_type i; ++ for(i = 0; i < k; ++i) { C[i] = 0; } ++ for(i = 0; i < n; ++i) { ++C[chr(i)]; } ++} ++static ++void ++getBuckets(const sais_index_type *C, sais_index_type *B, sais_index_type k, sais_bool_type end) { ++ sais_index_type i, sum = 0; ++ if(end) { for(i = 0; i < k; ++i) { sum += C[i]; B[i] = sum; } } ++ else { for(i = 0; i < k; ++i) { sum += C[i]; B[i] = sum - C[i]; } } ++} ++ ++/* sort all type LMS suffixes */ ++static ++void ++LMSsort1(const void *T, sais_index_type *SA, ++ sais_index_type *C, sais_index_type *B, ++ sais_index_type n, sais_index_type k, int cs) { ++ sais_index_type *b, i, j; ++ sais_index_type c0, c1; ++ ++ /* compute SAl */ ++ if(C == B) { getCounts(T, C, n, k, cs); } ++ getBuckets(C, B, k, 0); /* find starts of buckets */ ++ j = n - 1; ++ b = SA + B[c1 = chr(j)]; ++ --j; ++ *b++ = (chr(j) < c1) ? ~j : j; ++ for(i = 0; i < n; ++i) { ++ if(0 < (j = SA[i])) { ++ assert(chr(j) >= chr(j + 1)); ++ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } ++ assert(i < (b - SA)); ++ --j; ++ *b++ = (chr(j) < c1) ? ~j : j; ++ SA[i] = 0; ++ } else if(j < 0) { ++ SA[i] = ~j; ++ } ++ } ++ /* compute SAs */ ++ if(C == B) { getCounts(T, C, n, k, cs); } ++ getBuckets(C, B, k, 1); /* find ends of buckets */ ++ for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) { ++ if(0 < (j = SA[i])) { ++ assert(chr(j) <= chr(j + 1)); ++ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } ++ assert((b - SA) <= i); ++ --j; ++ *--b = (chr(j) > c1) ? ~(j + 1) : j; ++ SA[i] = 0; ++ } ++ } ++} ++static ++sais_index_type ++LMSpostproc1(const void *T, sais_index_type *SA, ++ sais_index_type n, sais_index_type m, int cs) { ++ sais_index_type i, j, p, q, plen, qlen, name; ++ sais_index_type c0, c1; ++ sais_bool_type diff; ++ ++ /* compact all the sorted substrings into the first m items of SA ++ 2*m must be not larger than n (proveable) */ ++ assert(0 < n); ++ for(i = 0; (p = SA[i]) < 0; ++i) { SA[i] = ~p; assert((i + 1) < n); } ++ if(i < m) { ++ for(j = i, ++i;; ++i) { ++ assert(i < n); ++ if((p = SA[i]) < 0) { ++ SA[j++] = ~p; SA[i] = 0; ++ if(j == m) { break; } ++ } ++ } ++ } ++ ++ /* store the length of all substrings */ ++ i = n - 1; j = n - 1; c0 = chr(n - 1); ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); ++ for(; 0 <= i;) { ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1)); ++ if(0 <= i) { ++ SA[m + ((i + 1) >> 1)] = j - i; j = i + 1; ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); ++ } ++ } ++ ++ /* find the lexicographic names of all substrings */ ++ for(i = 0, name = 0, q = n, qlen = 0; i < m; ++i) { ++ p = SA[i], plen = SA[m + (p >> 1)], diff = 1; ++ if((plen == qlen) && ((q + plen) < n)) { ++ for(j = 0; (j < plen) && (chr(p + j) == chr(q + j)); ++j) { } ++ if(j == plen) { diff = 0; } ++ } ++ if(diff != 0) { ++name, q = p, qlen = plen; } ++ SA[m + (p >> 1)] = name; ++ } ++ ++ return name; ++} ++static ++void ++LMSsort2(const void *T, sais_index_type *SA, ++ sais_index_type *C, sais_index_type *B, sais_index_type *D, ++ sais_index_type n, sais_index_type k, int cs) { ++ sais_index_type *b, i, j, t, d; ++ sais_index_type c0, c1; ++ assert(C != B); ++ ++ /* compute SAl */ ++ getBuckets(C, B, k, 0); /* find starts of buckets */ ++ j = n - 1; ++ b = SA + B[c1 = chr(j)]; ++ --j; ++ t = (chr(j) < c1); ++ j += n; ++ *b++ = (t & 1) ? ~j : j; ++ for(i = 0, d = 0; i < n; ++i) { ++ if(0 < (j = SA[i])) { ++ if(n <= j) { d += 1; j -= n; } ++ assert(chr(j) >= chr(j + 1)); ++ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } ++ assert(i < (b - SA)); ++ --j; ++ t = c0; t = (t << 1) | (chr(j) < c1); ++ if(D[t] != d) { j += n; D[t] = d; } ++ *b++ = (t & 1) ? ~j : j; ++ SA[i] = 0; ++ } else if(j < 0) { ++ SA[i] = ~j; ++ } ++ } ++ for(i = n - 1; 0 <= i; --i) { ++ if(0 < SA[i]) { ++ if(SA[i] < n) { ++ SA[i] += n; ++ for(j = i - 1; SA[j] < n; --j) { } ++ SA[j] -= n; ++ i = j; ++ } ++ } ++ } ++ ++ /* compute SAs */ ++ getBuckets(C, B, k, 1); /* find ends of buckets */ ++ for(i = n - 1, d += 1, b = SA + B[c1 = 0]; 0 <= i; --i) { ++ if(0 < (j = SA[i])) { ++ if(n <= j) { d += 1; j -= n; } ++ assert(chr(j) <= chr(j + 1)); ++ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } ++ assert((b - SA) <= i); ++ --j; ++ t = c0; t = (t << 1) | (chr(j) > c1); ++ if(D[t] != d) { j += n; D[t] = d; } ++ *--b = (t & 1) ? ~(j + 1) : j; ++ SA[i] = 0; ++ } ++ } ++} ++static ++sais_index_type ++LMSpostproc2(sais_index_type *SA, sais_index_type n, sais_index_type m) { ++ sais_index_type i, j, d, name; ++ ++ /* compact all the sorted LMS substrings into the first m items of SA */ ++ assert(0 < n); ++ for(i = 0, name = 0; (j = SA[i]) < 0; ++i) { ++ j = ~j; ++ if(n <= j) { name += 1; } ++ SA[i] = j; ++ assert((i + 1) < n); ++ } ++ if(i < m) { ++ for(d = i, ++i;; ++i) { ++ assert(i < n); ++ if((j = SA[i]) < 0) { ++ j = ~j; ++ if(n <= j) { name += 1; } ++ SA[d++] = j; SA[i] = 0; ++ if(d == m) { break; } ++ } ++ } ++ } ++ if(name < m) { ++ /* store the lexicographic names */ ++ for(i = m - 1, d = name + 1; 0 <= i; --i) { ++ if(n <= (j = SA[i])) { j -= n; --d; } ++ SA[m + (j >> 1)] = d; ++ } ++ } else { ++ /* unset flags */ ++ for(i = 0; i < m; ++i) { ++ if(n <= (j = SA[i])) { j -= n; SA[i] = j; } ++ } ++ } ++ ++ return name; ++} ++ ++/* compute SA and BWT */ ++static ++void ++induceSA(const void *T, sais_index_type *SA, ++ sais_index_type *C, sais_index_type *B, ++ sais_index_type n, sais_index_type k, int cs) { ++ sais_index_type *b, i, j; ++ sais_index_type c0, c1; ++ /* compute SAl */ ++ if(C == B) { getCounts(T, C, n, k, cs); } ++ getBuckets(C, B, k, 0); /* find starts of buckets */ ++ j = n - 1; ++ b = SA + B[c1 = chr(j)]; ++ *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j; ++ for(i = 0; i < n; ++i) { ++ j = SA[i], SA[i] = ~j; ++ if(0 < j) { ++ --j; ++ assert(chr(j) >= chr(j + 1)); ++ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } ++ assert(i < (b - SA)); ++ *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j; ++ } ++ } ++ /* compute SAs */ ++ if(C == B) { getCounts(T, C, n, k, cs); } ++ getBuckets(C, B, k, 1); /* find ends of buckets */ ++ for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) { ++ if(0 < (j = SA[i])) { ++ --j; ++ assert(chr(j) <= chr(j + 1)); ++ if((c0 = chr(j)) != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } ++ assert((b - SA) <= i); ++ *--b = ((j == 0) || (chr(j - 1) > c1)) ? ~j : j; ++ } else { ++ SA[i] = ~j; ++ } ++ } ++} ++static ++sais_index_type ++computeBWT(const void *T, sais_index_type *SA, ++ sais_index_type *C, sais_index_type *B, ++ sais_index_type n, sais_index_type k, int cs) { ++ sais_index_type *b, i, j, pidx = -1; ++ sais_index_type c0, c1; ++ /* compute SAl */ ++ if(C == B) { getCounts(T, C, n, k, cs); } ++ getBuckets(C, B, k, 0); /* find starts of buckets */ ++ j = n - 1; ++ b = SA + B[c1 = chr(j)]; ++ *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j; ++ for(i = 0; i < n; ++i) { ++ if(0 < (j = SA[i])) { ++ --j; ++ assert(chr(j) >= chr(j + 1)); ++ SA[i] = ~((sais_index_type)(c0 = chr(j))); ++ if(c0 != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } ++ assert(i < (b - SA)); ++ *b++ = ((0 < j) && (chr(j - 1) < c1)) ? ~j : j; ++ } else if(j != 0) { ++ SA[i] = ~j; ++ } ++ } ++ /* compute SAs */ ++ if(C == B) { getCounts(T, C, n, k, cs); } ++ getBuckets(C, B, k, 1); /* find ends of buckets */ ++ for(i = n - 1, b = SA + B[c1 = 0]; 0 <= i; --i) { ++ if(0 < (j = SA[i])) { ++ --j; ++ assert(chr(j) <= chr(j + 1)); ++ SA[i] = (c0 = chr(j)); ++ if(c0 != c1) { B[c1] = b - SA; b = SA + B[c1 = c0]; } ++ assert((b - SA) <= i); ++ *--b = ((0 < j) && (chr(j - 1) > c1)) ? ~((sais_index_type)chr(j - 1)) : j; ++ } else if(j != 0) { ++ SA[i] = ~j; ++ } else { ++ pidx = i; ++ } ++ } ++ return pidx; ++} ++ ++/* find the suffix array SA of T[0..n-1] in {0..255}^n */ ++static ++sais_index_type ++sais_main(const void *T, sais_index_type *SA, ++ sais_index_type fs, sais_index_type n, sais_index_type k, int cs, ++ sais_bool_type isbwt) { ++ sais_index_type *C, *B, *D, *RA, *b; ++ sais_index_type i, j, m, p, q, t, name, pidx = 0, newfs; ++ sais_index_type c0, c1; ++ unsigned int flags; ++ ++ assert((T != NULL) && (SA != NULL)); ++ assert((0 <= fs) && (0 < n) && (1 <= k)); ++ ++ if(k <= MINBUCKETSIZE) { ++ if((C = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { return -2; } ++ if(k <= fs) { ++ B = SA + (n + fs - k); ++ flags = 1; ++ } else { ++ if((B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { SAIS_MYFREE(C, k, sais_index_type); return -2; } ++ flags = 3; ++ } ++ } else if(k <= fs) { ++ C = SA + (n + fs - k); ++ if(k <= (fs - k)) { ++ B = C - k; ++ flags = 0; ++ } else if(k <= (MINBUCKETSIZE * 4)) { ++ if((B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { return -2; } ++ flags = 2; ++ } else { ++ B = C; ++ flags = 8; ++ } ++ } else { ++ if((C = B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { return -2; } ++ flags = 4 | 8; ++ } ++ if((n <= SAIS_LMSSORT2_LIMIT) && (2 <= (n / k))) { ++ if(flags & 1) { flags |= ((k * 2) <= (fs - k)) ? 32 : 16; } ++ else if((flags == 0) && ((k * 2) <= (fs - k * 2))) { flags |= 32; } ++ } ++ ++ /* stage 1: reduce the problem by at least 1/2 ++ sort all the LMS-substrings */ ++ getCounts(T, C, n, k, cs); getBuckets(C, B, k, 1); /* find ends of buckets */ ++ for(i = 0; i < n; ++i) { SA[i] = 0; } ++ b = &t; i = n - 1; j = n; m = 0; c0 = chr(n - 1); ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); ++ for(; 0 <= i;) { ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1)); ++ if(0 <= i) { ++ *b = j; b = SA + --B[c1]; j = i; ++m; ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); ++ } ++ } ++ ++ if(1 < m) { ++ if(flags & (16 | 32)) { ++ if(flags & 16) { ++ if((D = SAIS_MYMALLOC((size_t)k * 2, sais_index_type)) == NULL) { ++ if(flags & (1 | 4)) { SAIS_MYFREE(C, k, sais_index_type); } ++ if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); } ++ return -2; ++ } ++ } else { ++ D = B - k * 2; ++ } ++ assert((j + 1) < n); ++ ++B[chr(j + 1)]; ++ for(i = 0, j = 0; i < k; ++i) { ++ j += C[i]; ++ if(B[i] != j) { assert(SA[B[i]] != 0); SA[B[i]] += n; } ++ D[i] = D[i + k] = 0; ++ } ++ LMSsort2(T, SA, C, B, D, n, k, cs); ++ name = LMSpostproc2(SA, n, m); ++ if(flags & 16) { SAIS_MYFREE(D, k * 2, sais_index_type); } ++ } else { ++ LMSsort1(T, SA, C, B, n, k, cs); ++ name = LMSpostproc1(T, SA, n, m, cs); ++ } ++ } else if(m == 1) { ++ *b = j + 1; ++ name = 1; ++ } else { ++ name = 0; ++ } ++ ++ /* stage 2: solve the reduced problem ++ recurse if names are not yet unique */ ++ if(name < m) { ++ if(flags & 4) { SAIS_MYFREE(C, k, sais_index_type); } ++ if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); } ++ newfs = (n + fs) - (m * 2); ++ if((flags & (1 | 4 | 8)) == 0) { ++ if((k + name) <= newfs) { newfs -= k; } ++ else { flags |= 8; } ++ } ++ assert((n >> 1) <= (newfs + m)); ++ RA = SA + m + newfs; ++ for(i = m + (n >> 1) - 1, j = m - 1; m <= i; --i) { ++ if(SA[i] != 0) { ++ RA[j--] = SA[i] - 1; ++ } ++ } ++ if(sais_main(RA, SA, newfs, m, name, sizeof(sais_index_type), 0) != 0) { ++ if(flags & 1) { SAIS_MYFREE(C, k, sais_index_type); } ++ return -2; ++ } ++ ++ i = n - 1; j = m - 1; c0 = chr(n - 1); ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); ++ for(; 0 <= i;) { ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) <= c1)); ++ if(0 <= i) { ++ RA[j--] = i + 1; ++ do { c1 = c0; } while((0 <= --i) && ((c0 = chr(i)) >= c1)); ++ } ++ } ++ for(i = 0; i < m; ++i) { SA[i] = RA[SA[i]]; } ++ if(flags & 4) { ++ if((C = B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { return -2; } ++ } ++ if(flags & 2) { ++ if((B = SAIS_MYMALLOC((size_t)k, sais_index_type)) == NULL) { ++ if(flags & 1) { SAIS_MYFREE(C, k, sais_index_type); } ++ return -2; ++ } ++ } ++ } ++ ++ /* stage 3: induce the result for the original problem */ ++ if(flags & 8) { getCounts(T, C, n, k, cs); } ++ /* put all left-most S characters into their buckets */ ++ if(1 < m) { ++ getBuckets(C, B, k, 1); /* find ends of buckets */ ++ i = m - 1, j = n, p = SA[m - 1], c1 = chr(p); ++ do { ++ q = B[c0 = c1]; ++ while(q < j) { SA[--j] = 0; } ++ do { ++ SA[--j] = p; ++ if(--i < 0) { break; } ++ p = SA[i]; ++ } while((c1 = chr(p)) == c0); ++ } while(0 <= i); ++ while(0 < j) { SA[--j] = 0; } ++ } ++ if(isbwt == 0) { induceSA(T, SA, C, B, n, k, cs); } ++ else { pidx = computeBWT(T, SA, C, B, n, k, cs); } ++ if(flags & (1 | 4)) { SAIS_MYFREE(C, k, sais_index_type); } ++ if(flags & 2) { SAIS_MYFREE(B, k, sais_index_type); } ++ ++ return pidx; ++} ++ ++/*---------------------------------------------------------------------------*/ ++ ++sais_index_type ++sais(const unsigned char *T, sais_index_type *SA, int n) { ++ if((T == NULL) || (SA == NULL) || (n < 0)) { return -1; } ++ if(n <= 1) { if(n == 1) { SA[0] = 0; } return 0; } ++ return sais_main(T, SA, 0, n, UCHAR_SIZE, sizeof(unsigned char), 0); ++} ++ ++sais_index_type ++sais_int(const int *T, sais_index_type *SA, int n, int k) { ++ if((T == NULL) || (SA == NULL) || (n < 0) || (k <= 0)) { return -1; } ++ if(n <= 1) { if(n == 1) { SA[0] = 0; } return 0; } ++ return sais_main(T, SA, 0, n, k, sizeof(int), 0); ++} ++ ++sais_index_type ++sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n) { ++ int i; ++ sais_index_type pidx; ++ if((T == NULL) || (U == NULL) || (A == NULL) || (n < 0)) { return -1; } ++ if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; } ++ pidx = sais_main(T, A, 0, n, UCHAR_SIZE, sizeof(unsigned char), 1); ++ if(pidx < 0) { return pidx; } ++ U[0] = T[n - 1]; ++ for(i = 0; i < pidx; ++i) { U[i + 1] = (unsigned char)A[i]; } ++ for(i += 1; i < n; ++i) { U[i] = (unsigned char)A[i]; } ++ pidx += 1; ++ return pidx; ++} ++ ++sais_index_type ++sais_int_bwt(const sais_index_type *T, sais_index_type *U, sais_index_type *A, int n, int k) { ++ int i; ++ sais_index_type pidx; ++ if((T == NULL) || (U == NULL) || (A == NULL) || (n < 0) || (k <= 0)) { return -1; } ++ if(n <= 1) { if(n == 1) { U[0] = T[0]; } return n; } ++ pidx = sais_main(T, A, 0, n, k, sizeof(int), 1); ++ if(pidx < 0) { return pidx; } ++ U[0] = T[n - 1]; ++ for(i = 0; i < pidx; ++i) { U[i + 1] = A[i]; } ++ for(i += 1; i < n; ++i) { U[i] = A[i]; } ++ pidx += 1; ++ return pidx; ++} +diff --git a/sais.h b/sais.h +new file mode 100644 +index 0000000..1abd0af +--- /dev/null ++++ b/sais.h +@@ -0,0 +1,59 @@ ++/* ++ * sais.h for sais-lite ++ * Copyright (c) 2008-2010 Yuta Mori All Rights Reserved. ++ * ++ * Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef _SAIS_H ++#define _SAIS_H 1 ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++#include ++ ++#define sais_index_type off_t ++ ++/* find the suffix array SA of T[0..n-1] ++ use a working space (excluding T and SA) of at most 2n+O(lg n) */ ++sais_index_type ++sais(const unsigned char *T, sais_index_type *SA, int n); ++ ++/* find the suffix array SA of T[0..n-1] in {0..k-1}^n ++ use a working space (excluding T and SA) of at most MAX(4k,2n) */ ++sais_index_type ++sais_int(const int *T, sais_index_type *SA, int n, int k); ++ ++/* burrows-wheeler transform */ ++sais_index_type ++sais_bwt(const unsigned char *T, unsigned char *U, sais_index_type *A, int n); ++sais_index_type ++sais_int_bwt(const sais_index_type *T, sais_index_type *U, sais_index_type *A, int n, int k); ++ ++ ++#ifdef __cplusplus ++} /* extern "C" */ ++#endif /* __cplusplus */ ++ ++#endif /* _SAIS_H */ +-- +2.1.0 +