Commit a5e4be2f authored by Junio C Hamano's avatar Junio C Hamano

Merge branch 'ab/commit-graph-fixes'

Code cleanup with more careful error checking before using data
read from the commit-graph file.

* ab/commit-graph-fixes:
  commit-graph: improve & i18n error messages
  commit-graph write: don't die if the existing graph is corrupt
  commit-graph verify: detect inability to read the graph
  commit-graph: don't pass filename to load_commit_graph_one_fd_st()
  commit-graph: don't early exit(1) on e.g. "git status"
  commit-graph: fix segfault on e.g. "git status"
  commit-graph tests: test a graph that's too small
  commit-graph tests: split up corrupt_graph_and_verify()
parents f3c19f85 93b4405f
......@@ -42,6 +42,9 @@ static int graph_verify(int argc, const char **argv)
{
struct commit_graph *graph = NULL;
char *graph_name;
int open_ok;
int fd;
struct stat st;
static struct option builtin_commit_graph_verify_options[] = {
OPT_STRING(0, "object-dir", &opts.obj_dir,
......@@ -58,11 +61,16 @@ static int graph_verify(int argc, const char **argv)
opts.obj_dir = get_object_directory();
graph_name = get_commit_graph_filename(opts.obj_dir);
graph = load_commit_graph_one(graph_name);
open_ok = open_commit_graph(graph_name, &fd, &st);
if (!open_ok && errno == ENOENT)
return 0;
if (!open_ok)
die_errno(_("Could not open commit-graph '%s'"), graph_name);
graph = load_commit_graph_one_fd_st(fd, &st);
FREE_AND_NULL(graph_name);
if (!graph)
return 0;
return 1;
UNLEAK(graph);
return verify_commit_graph(the_repository, graph);
......@@ -72,6 +80,9 @@ static int graph_read(int argc, const char **argv)
{
struct commit_graph *graph = NULL;
char *graph_name;
int open_ok;
int fd;
struct stat st;
static struct option builtin_commit_graph_read_options[] = {
OPT_STRING(0, "object-dir", &opts.obj_dir,
......@@ -88,10 +99,14 @@ static int graph_read(int argc, const char **argv)
opts.obj_dir = get_object_directory();
graph_name = get_commit_graph_filename(opts.obj_dir);
graph = load_commit_graph_one(graph_name);
open_ok = open_commit_graph(graph_name, &fd, &st);
if (!open_ok)
die_errno(_("Could not open commit-graph '%s'"), graph_name);
graph = load_commit_graph_one_fd_st(fd, &st);
if (!graph)
die("graph file %s does not exist", graph_name);
return 1;
FREE_AND_NULL(graph_name);
......
This diff is collapsed.
......@@ -7,10 +7,12 @@
#include "cache.h"
#define GIT_TEST_COMMIT_GRAPH "GIT_TEST_COMMIT_GRAPH"
#define GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD "GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD"
struct commit;
char *get_commit_graph_filename(const char *obj_dir);
int open_commit_graph(const char *graph_file, int *fd, struct stat *st);
/*
* Given a commit struct, try to fill the commit struct info, including:
......@@ -52,7 +54,7 @@ struct commit_graph {
const unsigned char *chunk_extra_edges;
};
struct commit_graph *load_commit_graph_one(const char *graph_file);
struct commit_graph *load_commit_graph_one_fd_st(int fd, struct stat *st);
struct commit_graph *parse_commit_graph(void *graph_map, int fd,
size_t graph_size);
......
......@@ -89,6 +89,12 @@ static inline int repo_parse_commit(struct repository *r, struct commit *item)
{
return repo_parse_commit_gently(r, item, 0);
}
static inline int parse_commit_no_graph(struct commit *commit)
{
return repo_parse_commit_internal(the_repository, commit, 0, 0);
}
#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS
#define parse_commit_internal(item, quiet, use) repo_parse_commit_internal(the_repository, item, quiet, use)
#define parse_commit_gently(item, quiet) repo_parse_commit_gently(the_repository, item, quiet)
......
......@@ -366,6 +366,26 @@ GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \
GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4))
GRAPH_BYTE_FOOTER=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4 * $NUM_OCTOPUS_EDGES))
corrupt_graph_setup() {
cd "$TRASH_DIRECTORY/full" &&
test_when_finished mv commit-graph-backup $objdir/info/commit-graph &&
cp $objdir/info/commit-graph commit-graph-backup
}
corrupt_graph_verify() {
grepstr=$1
test_must_fail git commit-graph verify 2>test_err &&
grep -v "^+" test_err >err &&
test_i18ngrep "$grepstr" err &&
if test "$2" != "no-copy"
then
cp $objdir/info/commit-graph commit-graph-pre-write-test
fi &&
git status --short &&
GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD=true git commit-graph write &&
git commit-graph verify
}
# usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>]
# Manipulates the commit-graph file at the position
# by inserting the data, optionally zeroing the file
......@@ -376,19 +396,28 @@ corrupt_graph_and_verify() {
pos=$1
data="${2:-\0}"
grepstr=$3
cd "$TRASH_DIRECTORY/full" &&
corrupt_graph_setup &&
orig_size=$(wc -c < $objdir/info/commit-graph) &&
zero_pos=${4:-${orig_size}} &&
test_when_finished mv commit-graph-backup $objdir/info/commit-graph &&
cp $objdir/info/commit-graph commit-graph-backup &&
printf "$data" | dd of="$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc &&
dd of="$objdir/info/commit-graph" bs=1 seek="$zero_pos" if=/dev/null &&
generate_zero_bytes $(($orig_size - $zero_pos)) >>"$objdir/info/commit-graph" &&
test_must_fail git commit-graph verify 2>test_err &&
grep -v "^+" test_err >err &&
test_i18ngrep "$grepstr" err
corrupt_graph_verify "$grepstr"
}
test_expect_success POSIXPERM,SANITY 'detect permission problem' '
corrupt_graph_setup &&
chmod 000 $objdir/info/commit-graph &&
corrupt_graph_verify "Could not open" "no-copy"
'
test_expect_success 'detect too small' '
corrupt_graph_setup &&
echo "a small graph" >$objdir/info/commit-graph &&
corrupt_graph_verify "too small"
'
test_expect_success 'detect bad signature' '
corrupt_graph_and_verify 0 "\0" \
"graph signature"
......@@ -499,6 +528,7 @@ test_expect_success 'git fsck (checks commit-graph)' '
git fsck &&
corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \
"incorrect checksum" &&
cp commit-graph-pre-write-test $objdir/info/commit-graph &&
test_must_fail git fsck
'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment