Re: [PATCH v5 18/21] commit-graph: use string-list API for input
On 6/6/2018 8:45 AM, Derrick Stolee wrote: On 6/6/2018 8:26 AM, Ævar Arnfjörð Bjarmason wrote: On Wed, Jun 06 2018, Derrick Stolee wrote: On 6/6/2018 8:11 AM, Ævar Arnfjörð Bjarmason wrote: On Wed, Jun 06 2018, Derrick Stolee wrote: Signed-off-by: Derrick Stolee + string_list_clear(, 0); return 0; } This results in an invalid free() & segfault because you're freeing which may not have been allocated by string_list_init(). Good point. Did my tests not catch this? (seems it requires calling `git commit-graph write` with no `--stdin-packs` or `--stdin-commits`). Most of your tests (t5318-commit-graph.sh) segfaulted, but presumably you're on a more forgiving compiler/platform/options. I compiled with -O0 -g on clang 4.0.1-8 + Debian testing. I appreciate the extra platform testing. I'm using GCC on Ubuntu (gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0). While the errors didn't repro on my box, they did on the VSTS Linux build machines [1]. I created an internal PR just so I could run those tests (and on our OSX agents which use clang) and so I can verify I fixed the situation. I'll send a v6 soon so Junio only picks up a version that succeeds in tests. Thanks, -Stolee [1] https://github.com/Microsoft/vsts-agent-docker/blob/master/ubuntu/16.04/standard/Dockerfile What's installed on a VSTS Linux build agent
Re: [PATCH v5 18/21] commit-graph: use string-list API for input
On 6/6/2018 8:26 AM, Ævar Arnfjörð Bjarmason wrote: On Wed, Jun 06 2018, Derrick Stolee wrote: On 6/6/2018 8:11 AM, Ævar Arnfjörð Bjarmason wrote: On Wed, Jun 06 2018, Derrick Stolee wrote: Signed-off-by: Derrick Stolee --- builtin/commit-graph.c | 39 +-- commit-graph.c | 15 +++ commit-graph.h | 7 +++ 3 files changed, 23 insertions(+), 38 deletions(-) diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 3079cde6f9..d8eb8278b3 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -118,13 +118,9 @@ static int graph_read(int argc, const char **argv) static int graph_write(int argc, const char **argv) { - const char **pack_indexes = NULL; - int packs_nr = 0; - const char **commit_hex = NULL; - int commits_nr = 0; - const char **lines = NULL; - int lines_nr = 0; - int lines_alloc = 0; + struct string_list *pack_indexes = NULL; + struct string_list *commit_hex = NULL; + struct string_list lines; static struct option builtin_commit_graph_write_options[] = { OPT_STRING(0, "object-dir", _dir, @@ -150,32 +146,23 @@ static int graph_write(int argc, const char **argv) if (opts.stdin_packs || opts.stdin_commits) { struct strbuf buf = STRBUF_INIT; - lines_nr = 0; - lines_alloc = 128; - ALLOC_ARRAY(lines, lines_alloc); - - while (strbuf_getline(, stdin) != EOF) { - ALLOC_GROW(lines, lines_nr + 1, lines_alloc); - lines[lines_nr++] = strbuf_detach(, NULL); - } - - if (opts.stdin_packs) { - pack_indexes = lines; - packs_nr = lines_nr; - } - if (opts.stdin_commits) { - commit_hex = lines; - commits_nr = lines_nr; - } + string_list_init(, 0); + + while (strbuf_getline(, stdin) != EOF) + string_list_append(, strbuf_detach(, NULL)); + + if (opts.stdin_packs) + pack_indexes = + if (opts.stdin_commits) + commit_hex = } write_commit_graph(opts.obj_dir, pack_indexes, - packs_nr, commit_hex, - commits_nr, opts.append); + string_list_clear(, 0); return 0; } This results in an invalid free() & segfault because you're freeing which may not have been allocated by string_list_init(). Good point. Did my tests not catch this? (seems it requires calling `git commit-graph write` with no `--stdin-packs` or `--stdin-commits`). Most of your tests (t5318-commit-graph.sh) segfaulted, but presumably you're on a more forgiving compiler/platform/options. I compiled with -O0 -g on clang 4.0.1-8 + Debian testing. I appreciate the extra platform testing. I'm using GCC on Ubuntu (gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0). Monkeypatch on top which I used to fix it: diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 76423b3fa5..c7eb68aa3a 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -122,6 +122,7 @@ static int graph_write(int argc, const char **argv) struct string_list *pack_indexes = NULL; struct string_list *commit_hex = NULL; struct string_list lines; + int free_lines = 0; static struct option builtin_commit_graph_write_options[] = { OPT_STRING(0, "object-dir", _dir, @@ -155,6 +156,7 @@ static int graph_write(int argc, const char **argv) if (opts.stdin_packs || opts.stdin_commits) { struct strbuf buf = STRBUF_INIT; string_list_init(, 0); + free_lines = 1; while (strbuf_getline(, stdin) != EOF) string_list_append(, strbuf_detach(, NULL)); @@ -170,7 +172,8 @@ static int graph_write(int argc, const char **argv) commit_hex, opts.append); - string_list_clear(, 0); + if (free_lines) + string_list_clear(, 0); return 0; } But probably having a pointer to the struct which is NULL etc. is better. Wouldn't the easiest fix be to call `string_list_init(, 0)` outside of any conditional? Sure that works too. We'd be doing the init when we don't need it, but it's not like this part is performance critical or anything...
Re: [PATCH v5 18/21] commit-graph: use string-list API for input
On Wed, Jun 06 2018, Derrick Stolee wrote: > On 6/6/2018 8:11 AM, Ævar Arnfjörð Bjarmason wrote: >> On Wed, Jun 06 2018, Derrick Stolee wrote: >> >>> Signed-off-by: Derrick Stolee >>> --- >>> builtin/commit-graph.c | 39 +-- >>> commit-graph.c | 15 +++ >>> commit-graph.h | 7 +++ >>> 3 files changed, 23 insertions(+), 38 deletions(-) >>> diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c >>> index 3079cde6f9..d8eb8278b3 100644 >>> --- a/builtin/commit-graph.c >>> +++ b/builtin/commit-graph.c >>> @@ -118,13 +118,9 @@ static int graph_read(int argc, const char **argv) >>> >>> static int graph_write(int argc, const char **argv) >>> { >>> - const char **pack_indexes = NULL; >>> - int packs_nr = 0; >>> - const char **commit_hex = NULL; >>> - int commits_nr = 0; >>> - const char **lines = NULL; >>> - int lines_nr = 0; >>> - int lines_alloc = 0; >>> + struct string_list *pack_indexes = NULL; >>> + struct string_list *commit_hex = NULL; >>> + struct string_list lines; >>> >>> static struct option builtin_commit_graph_write_options[] = { >>> OPT_STRING(0, "object-dir", _dir, >>> @@ -150,32 +146,23 @@ static int graph_write(int argc, const char **argv) >>> >>> if (opts.stdin_packs || opts.stdin_commits) { >>> struct strbuf buf = STRBUF_INIT; >>> - lines_nr = 0; >>> - lines_alloc = 128; >>> - ALLOC_ARRAY(lines, lines_alloc); >>> - >>> - while (strbuf_getline(, stdin) != EOF) { >>> - ALLOC_GROW(lines, lines_nr + 1, lines_alloc); >>> - lines[lines_nr++] = strbuf_detach(, NULL); >>> - } >>> - >>> - if (opts.stdin_packs) { >>> - pack_indexes = lines; >>> - packs_nr = lines_nr; >>> - } >>> - if (opts.stdin_commits) { >>> - commit_hex = lines; >>> - commits_nr = lines_nr; >>> - } >>> + string_list_init(, 0); >>> + >>> + while (strbuf_getline(, stdin) != EOF) >>> + string_list_append(, strbuf_detach(, NULL)); >>> + >>> + if (opts.stdin_packs) >>> + pack_indexes = >>> + if (opts.stdin_commits) >>> + commit_hex = >>> } >>> >>> write_commit_graph(opts.obj_dir, >>>pack_indexes, >>> - packs_nr, >>>commit_hex, >>> - commits_nr, >>>opts.append); >>> >>> + string_list_clear(, 0); >>> return 0; >>> } >> This results in an invalid free() & segfault because you're freeing >> which may not have been allocated by string_list_init(). > > Good point. Did my tests not catch this? (seems it requires calling > `git commit-graph write` with no `--stdin-packs` or > `--stdin-commits`). Most of your tests (t5318-commit-graph.sh) segfaulted, but presumably you're on a more forgiving compiler/platform/options. I compiled with -O0 -g on clang 4.0.1-8 + Debian testing. >> >> Monkeypatch on top which I used to fix it: >> >> diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c >> index 76423b3fa5..c7eb68aa3a 100644 >> --- a/builtin/commit-graph.c >> +++ b/builtin/commit-graph.c >> @@ -122,6 +122,7 @@ static int graph_write(int argc, const char **argv) >> struct string_list *pack_indexes = NULL; >> struct string_list *commit_hex = NULL; >> struct string_list lines; >> + int free_lines = 0; >> >> static struct option builtin_commit_graph_write_options[] = { >> OPT_STRING(0, "object-dir", _dir, >> @@ -155,6 +156,7 @@ static int graph_write(int argc, const char **argv) >> if (opts.stdin_packs || opts.stdin_commits) { >> struct strbuf buf = STRBUF_INIT; >> string_list_init(, 0); >> + free_lines = 1; >> >> while (strbuf_getline(, stdin) != EOF) >> string_list_append(, strbuf_detach(, >> NULL)); >> @@ -170,7 +172,8 @@ static int graph_write(int argc, const char **argv) >> commit_hex, >> opts.append); >> >> - string_list_clear(, 0); >> + if (free_lines) >> + string_list_clear(, 0); >> return 0; >> } >> >> But probably having a pointer to the struct which is NULL etc. is >> better. > > Wouldn't the easiest fix be to call `string_list_init(, 0)` > outside of any conditional? Sure that works too. We'd be doing the init when we don't need it, but it's not like this part is performance critical or anything...
Re: [PATCH v5 18/21] commit-graph: use string-list API for input
On 6/6/2018 8:11 AM, Ævar Arnfjörð Bjarmason wrote: On Wed, Jun 06 2018, Derrick Stolee wrote: Signed-off-by: Derrick Stolee --- builtin/commit-graph.c | 39 +-- commit-graph.c | 15 +++ commit-graph.h | 7 +++ 3 files changed, 23 insertions(+), 38 deletions(-) diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 3079cde6f9..d8eb8278b3 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -118,13 +118,9 @@ static int graph_read(int argc, const char **argv) static int graph_write(int argc, const char **argv) { - const char **pack_indexes = NULL; - int packs_nr = 0; - const char **commit_hex = NULL; - int commits_nr = 0; - const char **lines = NULL; - int lines_nr = 0; - int lines_alloc = 0; + struct string_list *pack_indexes = NULL; + struct string_list *commit_hex = NULL; + struct string_list lines; static struct option builtin_commit_graph_write_options[] = { OPT_STRING(0, "object-dir", _dir, @@ -150,32 +146,23 @@ static int graph_write(int argc, const char **argv) if (opts.stdin_packs || opts.stdin_commits) { struct strbuf buf = STRBUF_INIT; - lines_nr = 0; - lines_alloc = 128; - ALLOC_ARRAY(lines, lines_alloc); - - while (strbuf_getline(, stdin) != EOF) { - ALLOC_GROW(lines, lines_nr + 1, lines_alloc); - lines[lines_nr++] = strbuf_detach(, NULL); - } - - if (opts.stdin_packs) { - pack_indexes = lines; - packs_nr = lines_nr; - } - if (opts.stdin_commits) { - commit_hex = lines; - commits_nr = lines_nr; - } + string_list_init(, 0); + + while (strbuf_getline(, stdin) != EOF) + string_list_append(, strbuf_detach(, NULL)); + + if (opts.stdin_packs) + pack_indexes = + if (opts.stdin_commits) + commit_hex = } write_commit_graph(opts.obj_dir, pack_indexes, - packs_nr, commit_hex, - commits_nr, opts.append); + string_list_clear(, 0); return 0; } This results in an invalid free() & segfault because you're freeing which may not have been allocated by string_list_init(). Good point. Did my tests not catch this? (seems it requires calling `git commit-graph write` with no `--stdin-packs` or `--stdin-commits`). Monkeypatch on top which I used to fix it: diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 76423b3fa5..c7eb68aa3a 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -122,6 +122,7 @@ static int graph_write(int argc, const char **argv) struct string_list *pack_indexes = NULL; struct string_list *commit_hex = NULL; struct string_list lines; + int free_lines = 0; static struct option builtin_commit_graph_write_options[] = { OPT_STRING(0, "object-dir", _dir, @@ -155,6 +156,7 @@ static int graph_write(int argc, const char **argv) if (opts.stdin_packs || opts.stdin_commits) { struct strbuf buf = STRBUF_INIT; string_list_init(, 0); + free_lines = 1; while (strbuf_getline(, stdin) != EOF) string_list_append(, strbuf_detach(, NULL)); @@ -170,7 +172,8 @@ static int graph_write(int argc, const char **argv) commit_hex, opts.append); - string_list_clear(, 0); + if (free_lines) + string_list_clear(, 0); return 0; } But probably having a pointer to the struct which is NULL etc. is better. Wouldn't the easiest fix be to call `string_list_init(, 0)` outside of any conditional? Thanks, -Stolee
Re: [PATCH v5 18/21] commit-graph: use string-list API for input
On Wed, Jun 06 2018, Derrick Stolee wrote: > Signed-off-by: Derrick Stolee > --- > builtin/commit-graph.c | 39 +-- > commit-graph.c | 15 +++ > commit-graph.h | 7 +++ > 3 files changed, 23 insertions(+), 38 deletions(-) > diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c > index 3079cde6f9..d8eb8278b3 100644 > --- a/builtin/commit-graph.c > +++ b/builtin/commit-graph.c > @@ -118,13 +118,9 @@ static int graph_read(int argc, const char **argv) > > static int graph_write(int argc, const char **argv) > { > - const char **pack_indexes = NULL; > - int packs_nr = 0; > - const char **commit_hex = NULL; > - int commits_nr = 0; > - const char **lines = NULL; > - int lines_nr = 0; > - int lines_alloc = 0; > + struct string_list *pack_indexes = NULL; > + struct string_list *commit_hex = NULL; > + struct string_list lines; > > static struct option builtin_commit_graph_write_options[] = { > OPT_STRING(0, "object-dir", _dir, > @@ -150,32 +146,23 @@ static int graph_write(int argc, const char **argv) > > if (opts.stdin_packs || opts.stdin_commits) { > struct strbuf buf = STRBUF_INIT; > - lines_nr = 0; > - lines_alloc = 128; > - ALLOC_ARRAY(lines, lines_alloc); > - > - while (strbuf_getline(, stdin) != EOF) { > - ALLOC_GROW(lines, lines_nr + 1, lines_alloc); > - lines[lines_nr++] = strbuf_detach(, NULL); > - } > - > - if (opts.stdin_packs) { > - pack_indexes = lines; > - packs_nr = lines_nr; > - } > - if (opts.stdin_commits) { > - commit_hex = lines; > - commits_nr = lines_nr; > - } > + string_list_init(, 0); > + > + while (strbuf_getline(, stdin) != EOF) > + string_list_append(, strbuf_detach(, NULL)); > + > + if (opts.stdin_packs) > + pack_indexes = > + if (opts.stdin_commits) > + commit_hex = > } > > write_commit_graph(opts.obj_dir, > pack_indexes, > -packs_nr, > commit_hex, > -commits_nr, > opts.append); > > + string_list_clear(, 0); > return 0; > } This results in an invalid free() & segfault because you're freeing which may not have been allocated by string_list_init(). Monkeypatch on top which I used to fix it: diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c index 76423b3fa5..c7eb68aa3a 100644 --- a/builtin/commit-graph.c +++ b/builtin/commit-graph.c @@ -122,6 +122,7 @@ static int graph_write(int argc, const char **argv) struct string_list *pack_indexes = NULL; struct string_list *commit_hex = NULL; struct string_list lines; + int free_lines = 0; static struct option builtin_commit_graph_write_options[] = { OPT_STRING(0, "object-dir", _dir, @@ -155,6 +156,7 @@ static int graph_write(int argc, const char **argv) if (opts.stdin_packs || opts.stdin_commits) { struct strbuf buf = STRBUF_INIT; string_list_init(, 0); + free_lines = 1; while (strbuf_getline(, stdin) != EOF) string_list_append(, strbuf_detach(, NULL)); @@ -170,7 +172,8 @@ static int graph_write(int argc, const char **argv) commit_hex, opts.append); - string_list_clear(, 0); + if (free_lines) + string_list_clear(, 0); return 0; } But probably having a pointer to the struct which is NULL etc. is better.