From 2a1bd45b2e44a7ba23dfe67307e7755d0a22e5d6 Mon Sep 17 00:00:00 2001 From: Kevin Willford Date: Fri, 31 Mar 2017 17:32:14 +0000 Subject: [PATCH 1/4] name-hash: fix buffer overrun Add check for the end of the entries for the thread partition. Add test for lazy init name hash with specific directory structure The lazy init hash name was causing a buffer overflow when the last entry in the index was multiple folder deep with parent folders that did not have any files in them. This adds a test for the boundary condition of the thread partitions with the folder structure that was triggering the buffer overflow. The fix was to check if it is the last entry for the thread partition in the handle_range_dir and not try to use the next entry in the cache. Signed-off-by: Kevin Willford Signed-off-by: Johannes Schindelin Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- name-hash.c | 4 +++- t/t3008-ls-files-lazy-init-name-hash.sh | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100755 t/t3008-ls-files-lazy-init-name-hash.sh diff --git a/name-hash.c b/name-hash.c index cac313c78d..39309efb7f 100644 --- a/name-hash.c +++ b/name-hash.c @@ -342,7 +342,9 @@ static int handle_range_dir( * Scan forward in the index array for index entries having the same * path prefix (that are also in this directory). */ - if (strncmp(istate->cache[k_start + 1]->name, prefix->buf, prefix->len) > 0) + if (k_start + 1 >= k_end) + k = k_end; + else if (strncmp(istate->cache[k_start + 1]->name, prefix->buf, prefix->len) > 0) k = k_start + 1; else if (strncmp(istate->cache[k_end - 1]->name, prefix->buf, prefix->len) == 0) k = k_end; diff --git a/t/t3008-ls-files-lazy-init-name-hash.sh b/t/t3008-ls-files-lazy-init-name-hash.sh new file mode 100755 index 0000000000..971975bff4 --- /dev/null +++ b/t/t3008-ls-files-lazy-init-name-hash.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +test_description='Test the lazy init name hash with various folder structures' + +. ./test-lib.sh + +test_expect_success 'no buffer overflow in lazy_init_name_hash' ' + ( + test_seq 2000 | sed "s/^/a_/" + echo b/b/b + test_seq 2000 | sed "s/^/c_/" + test_seq 50 | sed "s/^/d_/" | tr "\n" "/"; echo d + ) | + sed -e "s/^/100644 $EMPTY_BLOB /" | + git update-index --index-info && + test-lazy-init-name-hash -m +' + +test_done From e3482ccf27b8278289f899cbb294696389a9e1c8 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Mon, 3 Apr 2017 15:16:41 +0000 Subject: [PATCH 2/4] test-online-cpus: helper to return cpu count Created helper executable to print the value of online_cpus() allowing multi-threaded tests to be skipped when appropriate. Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- Makefile | 1 + t/helper/.gitignore | 1 + t/helper/test-online-cpus.c | 8 ++++++++ 3 files changed, 10 insertions(+) create mode 100644 t/helper/test-online-cpus.c diff --git a/Makefile b/Makefile index 061d9ea884..dc0c3689b1 100644 --- a/Makefile +++ b/Makefile @@ -619,6 +619,7 @@ TEST_PROGRAMS_NEED_X += test-line-buffer TEST_PROGRAMS_NEED_X += test-match-trees TEST_PROGRAMS_NEED_X += test-mergesort TEST_PROGRAMS_NEED_X += test-mktemp +TEST_PROGRAMS_NEED_X += test-online-cpus TEST_PROGRAMS_NEED_X += test-parse-options TEST_PROGRAMS_NEED_X += test-path-utils TEST_PROGRAMS_NEED_X += test-prio-queue diff --git a/t/helper/.gitignore b/t/helper/.gitignore index 758ed2e8fa..b05d67c237 100644 --- a/t/helper/.gitignore +++ b/t/helper/.gitignore @@ -16,6 +16,7 @@ /test-match-trees /test-mergesort /test-mktemp +/test-online-cpus /test-parse-options /test-path-utils /test-prio-queue diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c new file mode 100644 index 0000000000..06c09c6b88 --- /dev/null +++ b/t/helper/test-online-cpus.c @@ -0,0 +1,8 @@ +#include "git-compat-util.h" +#include "thread-utils.h" + +int cmd_main(int argc, const char **argv) +{ + printf("%d\n", online_cpus()); + return 0; +} From 845eec2b64d6a064ee7b453a77a309a419806896 Mon Sep 17 00:00:00 2001 From: Kevin Willford Date: Mon, 3 Apr 2017 15:16:42 +0000 Subject: [PATCH 3/4] t3008: skip lazy-init test on a single-core box The lazy-init codepath will not be exercised uniless threaded. Skip the entire test on a single-core box. Also replace a hard-coded constant of 2000 (number of cache entries to manifacture for tests) with a variable with a human readable name. Signed-off-by: Kevin Willford Signed-off-by: Johannes Schindelin Signed-off-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/t3008-ls-files-lazy-init-name-hash.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/t/t3008-ls-files-lazy-init-name-hash.sh b/t/t3008-ls-files-lazy-init-name-hash.sh index 971975bff4..bdf5198b7e 100755 --- a/t/t3008-ls-files-lazy-init-name-hash.sh +++ b/t/t3008-ls-files-lazy-init-name-hash.sh @@ -4,14 +4,22 @@ test_description='Test the lazy init name hash with various folder structures' . ./test-lib.sh +if test 1 -eq $($GIT_BUILD_DIR/t/helper/test-online-cpus) +then + skip_all='skipping lazy-init tests, single cpu' + test_done +fi + +LAZY_THREAD_COST=2000 + test_expect_success 'no buffer overflow in lazy_init_name_hash' ' ( - test_seq 2000 | sed "s/^/a_/" + test_seq $LAZY_THREAD_COST | sed "s/^/a_/" echo b/b/b - test_seq 2000 | sed "s/^/c_/" + test_seq $LAZY_THREAD_COST | sed "s/^/c_/" test_seq 50 | sed "s/^/d_/" | tr "\n" "/"; echo d ) | - sed -e "s/^/100644 $EMPTY_BLOB /" | + sed "s/^/100644 $EMPTY_BLOB /" | git update-index --index-info && test-lazy-init-name-hash -m ' From c9d4999155700651a37f4eb577cec1f4b5b8d6be Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 18 Apr 2017 16:24:07 +0200 Subject: [PATCH 4/4] p0004: make perf test executable It looks like in 89c3b0ad43 (name-hash: add perf test for lazy_init_name_hash, 2017-03-23) p0004 was not created with the execute unix rights. Let's fix that. Signed-off-by: Christian Couder Acked-by: Jeff Hostetler Signed-off-by: Junio C Hamano --- t/perf/p0004-lazy-init-name-hash.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 t/perf/p0004-lazy-init-name-hash.sh diff --git a/t/perf/p0004-lazy-init-name-hash.sh b/t/perf/p0004-lazy-init-name-hash.sh old mode 100644 new mode 100755