ref-filter: don't look for objects when outside of a repository

The command 'git ls-remote --sort=authordate <remote>' segfaults when run outside of a repository, ever since the introduction of its '--sort' option in 1fb20dfd8e (ls-remote: create '--sort' option, 2018-04-09). While in general the 'git ls-remote' command can be run outside of a repository just fine, its '--sort=<key>' option with certain keys does require access to the referenced objects. This sorting is implemented using the generic ref-filter sorting facility, which already handles missing objects gracefully with the appropriate 'missing object deadbeef for HEAD' message. However, being generic means that it checks replace refs while trying to retrieve an object, and while doing so it accesses the 'git_replace_ref_base' variable, which has not been initialized and is still a NULL pointer when outside of a repository, thus causing the segfault. Make ref-filter more careful upfront while parsing the format string, and make it error out when encountering a format atom requiring object access when we are not in a repository. Also add a test to ensure that 'git ls-remote --sort' fails gracefully when executed outside of a repository. Reported-by: H.Merijn Brand <h.m.brand@xs4all.nl> Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

SZEDER Gábor committed Nov 14, 2018 at 13:27 UTC 47bd3d0c14f081a3ea32b0720f7d59559802904d
2 files changed +10
ref-filter.c
+4
@@ -534,6 +534,10 @@ static int parse_ref_filter_atom(const struct ref_format *format,
534 if (ARRAY_SIZE(valid_atom) <= i)
535 return strbuf_addf_ret(err, -1, _("unknown field name: %.*s"),
536 (int)(ep-atom), atom);
537 + if (valid_atom[i].source != SOURCE_NONE && !have_git_dir())
538 + return strbuf_addf_ret(err, -1,
539 + _("not a git repository, but the field '%.*s' requires access to object data"),
540 + (int)(ep-atom), atom);
541
542 /* Add it in, including the deref prefix */
543 at = used_atom_cnt;
t/t5512-ls-remote.sh
+6
@@ -302,6 +302,12 @@ test_expect_success 'ls-remote works outside repository' '
302 nongit git ls-remote dst.git
303 '
304
305 +test_expect_success 'ls-remote --sort fails gracefully outside repository' '
306 + # Use a sort key that requires access to the referenced objects.
307 + nongit test_must_fail git ls-remote --sort=authordate "$TRASH_DIRECTORY" 2>err &&
308 + test_i18ngrep "^fatal: not a git repository, but the field '\''authordate'\'' requires access to object data" err
309 +'
310 +
311 test_expect_success 'ls-remote patterns work with all protocol versions' '
312 git for-each-ref --format="%(objectname) %(refname)" \
313 refs/heads/master refs/remotes/origin/master >expect &&