Package: release.debian.org Severity: normal Tags: stretch User: release.debian....@packages.debian.org Usertags: pu
>From the jdupes upstream: "All versions from 1.5.1 up to 1.7 have potentially serious bugs in the internal memory allocator which caused crashes on Debian ARM and macOS Sierra. These should be updated to a minimum of v1.8 if at all possible. If that isn't possible, the following commits improving/fixing the internal memory allocator should be patched into the old versions: e2bebfdbadd0474a6b5f16f46ce1b48201d75150 78e06c3eb1f1cfdebf8ca555f5c699b69b3a9aad 1f2fe4a0c1bca7486cfc5aa84877246e90d1321a 1498a04e2ad5ba6cef6e94c5f64408d35670f7b8" This upload will close #914078 Thanks in advance. Regards, Eriberto
diff -Nru jdupes-1.7/debian/changelog jdupes-1.7/debian/changelog --- jdupes-1.7/debian/changelog 2017-02-06 22:19:51.000000000 -0200 +++ jdupes-1.7/debian/changelog 2018-11-19 00:10:16.000000000 -0200 @@ -1,3 +1,10 @@ +jdupes (1.7-2+deb9u1) stretch; urgency=medium + + * debian/patches/20_fix-crash-arm.patch: add to fix a potential crash in + ARM. Thanks to Jody Bruchon <j...@jodybruchon.com>. (Closes: #914078) + + -- Joao Eriberto Mota Filho <eribe...@debian.org> Mon, 19 Nov 2018 00:10:16 -0200 + jdupes (1.7-2) unstable; urgency=medium * debian/patches/10_fix-segfault.patch: added to fix a segmentation fault in diff -Nru jdupes-1.7/debian/patches/20_fix-crash-arm.patch jdupes-1.7/debian/patches/20_fix-crash-arm.patch --- jdupes-1.7/debian/patches/20_fix-crash-arm.patch 1969-12-31 21:00:00.000000000 -0300 +++ jdupes-1.7/debian/patches/20_fix-crash-arm.patch 2018-11-19 00:10:16.000000000 -0200 @@ -0,0 +1,250 @@ +Description: fix a potential crash in ARM. + From the jdupes upstream: + + "All versions from 1.5.1 up to 1.7 have potentially serious bugs in the + internal memory allocator which caused crashes on Debian ARM and macOS + Sierra. These should be updated to a minimum of v1.8 if at all possible. + + If that isn't possible, the following commits improving/fixing the internal + memory allocator should be patched into the old versions: + + e2bebfdbadd0474a6b5f16f46ce1b48201d75150 + 78e06c3eb1f1cfdebf8ca555f5c699b69b3a9aad + 1f2fe4a0c1bca7486cfc5aa84877246e90d1321a + 1498a04e2ad5ba6cef6e94c5f64408d35670f7b8 +Author: Jody Bruchon <j...@jodybruchon.com> +Origin: upstream + https://github.com/jbruchon/jdupes/commit/e2bebfdbadd0474a6b5f16f46ce1b48201d75150.patch + https://github.com/jbruchon/jdupes/commit/78e06c3eb1f1cfdebf8ca555f5c699b69b3a9aad.patch + https://github.com/jbruchon/jdupes/commit/1f2fe4a0c1bca7486cfc5aa84877246e90d1321a.patch + https://github.com/jbruchon/jdupes/commit/1498a04e2ad5ba6cef6e94c5f64408d35670f7b8.patch +Bug-Debian: https://bugs.debian.org/914078 +Last-Update: 2017-01-19 +--- jdupes-1.7.orig/jdupes.c ++++ jdupes-1.7/jdupes.c +@@ -501,18 +501,24 @@ extern int check_conditions(const file_t + } + + +-/* Create a new traversal check object */ +-static int travdone_alloc(struct travdone **trav, const char * const restrict dir) ++/* Create a new traversal check object and initialize its values */ ++static struct travdone *travdone_alloc(const jdupes_ino_t inode, const dev_t device) + { +- *trav = string_malloc(sizeof(struct travdone)); +- if (*trav == NULL) { ++ struct travdone *trav; ++ ++ LOUD(fprintf(stderr, "travdone_alloc(%jd, %jd)\n", (intmax_t)inode, (intmax_t)device);) ++ ++ trav = (struct travdone *)string_malloc(sizeof(struct travdone)); ++ if (trav == NULL) { + LOUD(fprintf(stderr, "travdone_alloc: malloc returned NULL\n");) +- return -1; ++ return NULL; + } +- (*trav)->left = NULL; +- (*trav)->right = NULL; +- if (getdirstats(dir, &((*trav)->inode), &((*trav)->device)) != 0) return -1; +- return 0; ++ trav->left = NULL; ++ trav->right = NULL; ++ trav->inode = inode; ++ trav->device = device; ++ LOUD(fprintf(stderr, "travdone_alloc returned %p\n", (void *)trav);) ++ return trav; + } + + +@@ -545,22 +551,23 @@ static void grokdir(const char * const r + LOUD(fprintf(stderr, "grokdir: scanning '%s' (order %d)\n", dir, user_dir_count)); + + /* Double traversal prevention tree */ ++ if (getdirstats(dir, &inode, &device) != 0) goto error_travdone; + if (travdone_head == NULL) { +- if (travdone_alloc(&travdone_head, dir) != 0) goto error_travdone; ++ travdone_head = travdone_alloc(inode, device); ++ if (travdone_head == NULL) goto error_travdone; + } else { +- if (getdirstats(dir, &inode, &device) != 0) goto error_travdone; + traverse = travdone_head; + while (1) { + /* Don't re-traverse directories we've already seen */ + if (inode == traverse->inode && device == traverse->device) { + LOUD(fprintf(stderr, "already seen dir '%s', skipping\n", dir);) + return; +- } +- if (inode >= traverse->inode) { ++ } else if (inode > traverse->inode || (inode == traverse->inode && device > traverse->device)) { + /* Traverse right */ + if (traverse->right == NULL) { + LOUD(fprintf(stderr, "traverse dir right '%s'\n", dir);) +- if (travdone_alloc(&(traverse->right), dir) != 0) goto error_travdone; ++ traverse->right = travdone_alloc(inode, device); ++ if (traverse->right == NULL) goto error_travdone; + break; + } + traverse = traverse->right; +@@ -569,7 +576,8 @@ static void grokdir(const char * const r + /* Traverse left */ + if (traverse->left == NULL) { + LOUD(fprintf(stderr, "traverse dir left '%s'\n", dir);) +- if (travdone_alloc(&(traverse->left), dir) != 0) goto error_travdone; ++ traverse->left = travdone_alloc(inode, device); ++ if (traverse->left == NULL) goto error_travdone; + break; + } + traverse = traverse->left; +--- jdupes-1.7.orig/string_malloc.c ++++ jdupes-1.7/string_malloc.c +@@ -30,7 +30,7 @@ + #endif + + static void *sma_head = NULL; +-static uintptr_t *sma_curpage = NULL; ++static uintptr_t *sma_lastpage = NULL; + static unsigned int sma_pages = 0; + static void *sma_freelist[SMA_MAX_FREE]; + static int sma_freelist_cnt = 0; +@@ -52,9 +52,9 @@ uintmax_t sma_free_tails = 0; + /* Scan the freed chunk list for a suitably sized object */ + static inline void *scan_freelist(const size_t size) + { +- size_t *object, *min_p; ++ size_t *min_p, *object; + size_t sz, min = 0; +- int i, used = 0, min_i = -1; ++ int i, used = 0; + + /* Don't bother scanning if the list is empty */ + if (sma_freelist_cnt == 0) return NULL; +@@ -74,9 +74,9 @@ static inline void *scan_freelist(const + /* Skip smaller objects */ + if (sz < size) continue; + /* Object is big enough; record if it's the new minimum */ +- if (min == 0 || sz <= min) { ++ if (min == 0 || sz < min) { + min = sz; +- min_i = i; ++ min_p = object; + /* Always stop scanning if exact sized object found */ + if (sz == size) break; + } +@@ -85,9 +85,8 @@ static inline void *scan_freelist(const + /* Enhancement TODO: split the free item if it's big enough */ + + /* Return smallest object found and delete from free list */ +- if (min_i != -1) { +- min_p = sma_freelist[min_i]; +- sma_freelist[min_i] = NULL; ++ if (min != 0) { ++ sma_freelist[i] = NULL; + sma_freelist_cnt--; + min_p++; + return (void *)min_p; +@@ -108,10 +107,10 @@ static inline void *string_malloc_page(v + *pageptr = (uintptr_t)NULL; + + /* Link previous page to this page, if applicable */ +- if (sma_curpage != NULL) *sma_curpage = (uintptr_t)pageptr; ++ if (sma_lastpage != NULL) *sma_lastpage = (uintptr_t)pageptr; + + /* Update last page pointers and total page counter */ +- sma_curpage = pageptr; ++ sma_lastpage = pageptr; + sma_pages++; + + return (void *)pageptr; +@@ -120,7 +119,7 @@ static inline void *string_malloc_page(v + + void *string_malloc(size_t len) + { +- const void * restrict page = (char *)sma_curpage; ++ const void * restrict page = (char *)sma_lastpage; + static size_t *address; + + /* Calling with no actual length is invalid */ +@@ -131,6 +130,8 @@ void *string_malloc(size_t len) + len &= ~(sizeof(uintptr_t) - 1); + len += sizeof(uintptr_t); + } ++ /* Make room for size prefix */ ++ len += sizeof(size_t); + + /* Pass-through allocations larger than maximum object size to malloc() */ + if (len > (SMA_PAGE_SIZE - sizeof(uintptr_t) - sizeof(size_t))) { +@@ -150,7 +151,7 @@ void *string_malloc(size_t len) + for (int i = 0; i < SMA_MAX_FREE; i++) sma_freelist[i] = NULL; + /* Allocate first page and set up for first allocation */ + sma_head = string_malloc_page(); +- if (sma_head == NULL) return NULL; ++ if (!sma_head) return NULL; + sma_nextfree = sizeof(uintptr_t); + page = sma_head; + } +@@ -163,20 +164,17 @@ void *string_malloc(size_t len) + } + + /* Allocate new page if this object won't fit */ +- if ((sma_nextfree + len + sizeof(size_t)) > SMA_PAGE_SIZE) { ++ if ((sma_nextfree + len) > SMA_PAGE_SIZE) { + size_t sz; + size_t *tailaddr; + /* See if remaining space is usable */ +- if (sma_freelist_cnt < SMA_MAX_FREE && (sma_nextfree + sizeof(size_t)) < SMA_PAGE_SIZE) { +- /* Get remaining space size minus page linkage and obj size prefix */ +- sz = sma_nextfree + sizeof(size_t) + SMA_MIN_SLACK; +- +- if (sz <= SMA_PAGE_SIZE) { +- sz = SMA_PAGE_SIZE - sma_nextfree - sizeof(size_t); ++ if (sma_freelist_cnt < SMA_MAX_FREE && sma_nextfree < SMA_PAGE_SIZE) { ++ /* Get total remaining space size */ ++ sz = SMA_PAGE_SIZE - sma_nextfree; ++ if (sz >= (SMA_MIN_SLACK + sizeof(size_t))) { + tailaddr = (size_t *)((uintptr_t)page + sma_nextfree); +- *tailaddr = (size_t)sz; +- tailaddr++; +- string_free(tailaddr); ++ *tailaddr = sz; ++ string_free(tailaddr + 1); + DBG(sma_free_tails++;) + } + } +@@ -190,7 +188,7 @@ void *string_malloc(size_t len) + /* Prefix object with its size */ + *address = len; + address++; +- sma_nextfree += len + sizeof(size_t); ++ sma_nextfree += len; + + DBG(sma_allocs++;) + return (void *)address; +@@ -208,7 +206,7 @@ void string_free(void * const restrict a + goto sf_failed; + + /* Tiny objects keep big ones from being freed; ignore them */ +- if (*(size_t *)((uintptr_t)addr - sizeof(size_t)) < SMA_MIN_SLACK) ++ if (*(size_t *)((uintptr_t)addr - sizeof(size_t)) < (SMA_MIN_SLACK + sizeof(size_t))) + goto sf_failed; + + /* Add object to free list */ +@@ -231,15 +229,14 @@ sf_failed: + /* Destroy all allocated pages */ + void string_malloc_destroy(void) + { +- void *cur; ++ uintptr_t *cur; + uintptr_t *next; + +- cur = (void *)sma_head; +- if (sma_head == NULL) return; ++ cur = sma_head; + while (sma_pages > 0) { +- next = (uintptr_t *)*(uintptr_t *)cur; ++ next = (uintptr_t *)*cur; + free(cur); +- cur = (void *)next; ++ cur = next; + sma_pages--; + } + sma_head = NULL; diff -Nru jdupes-1.7/debian/patches/series jdupes-1.7/debian/patches/series --- jdupes-1.7/debian/patches/series 2017-02-06 22:17:30.000000000 -0200 +++ jdupes-1.7/debian/patches/series 2018-11-19 00:10:16.000000000 -0200 @@ -1 +1,2 @@ 10_fix-segfault.patch +20_fix-crash-arm.patch