Junio C Hamano <gitster@xxxxxxxxx> writes: > Lukas Fleischer <git@xxxxxxxxxxxxxx> writes: > >> The helper functions prepare_final() and prepare_initial() return a >> pointer to a string that is a member of an object in the revs->pending >> array. This array is later rebuilt when running prepare_revision_walk() >> which potentially transforms the pointer target into a bogus string. Fix >> this by maintaining a copy of the original string. >> >> Signed-off-by: Lukas Fleischer <git@xxxxxxxxxxxxxx> >> --- >> The bug manifests when running `git blame HEAD^ -- nonexistent.file`. > > Before 1da1e07c (clean up name allocation in prepare_revision_walk, > 2014-10-15), these strings used to be non-volatile; they were instead > leaked more or less deliberately. But these days, these strings are > cleared, so your patch is absolutely the right thing to do. > > Thanks for catching and fixing. This fix needs to go to the 2.2.x > maintenance track. Sigh, but not so fast. With the patch applied on top of 1da1e07c (or the result merged to 'next' for that matter), I see test breakages in many places "git blame" is used, e.g. t7010. Did you run the test suite? This is because it is perfectly normal for prepare_final() to return NULL. Unconditionally running xstrdup() would of course fail. >> Note that I could have reduced code churn a little by moving the >> xstrdup() invocations to the call sites. However, I think that the >> return value of these functions should not depend on the consistency of >> a volatile data structure. On the other hand, you might also argue that >> there currently are only two call sites and that the functions are >> marked static, so if you prefer the less intrusive version, please let >> me know. > > FWIW, I agree that this can be argued either way. > > If we had a common low-level API that is used by short-term users to > grab these names, it would be reasonable to make it the callers' > responsibility to strdup() the return values for safekeeping if they > want to keep using them long after the function returns. But I > agree that prepare_final/prepare_initial are not such a low-level > common API functions. I do not care too much about who does the > strdup(), either the callers of prepare_* or the callee. > >> >> builtin/blame.c | 12 +++++++----- >> 1 file changed, 7 insertions(+), 5 deletions(-) >> >> diff --git a/builtin/blame.c b/builtin/blame.c >> index 303e217..34d6f4f 100644 >> --- a/builtin/blame.c >> +++ b/builtin/blame.c >> @@ -2390,7 +2390,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt, >> return commit; >> } >> >> -static const char *prepare_final(struct scoreboard *sb) >> +static char *prepare_final(struct scoreboard *sb) >> { >> int i; >> const char *final_commit_name = NULL; >> @@ -2415,10 +2415,10 @@ static const char *prepare_final(struct scoreboard *sb) >> sb->final = (struct commit *) obj; >> final_commit_name = revs->pending.objects[i].name; >> } >> - return final_commit_name; >> + return xstrdup(final_commit_name); >> } >> >> -static const char *prepare_initial(struct scoreboard *sb) >> +static char *prepare_initial(struct scoreboard *sb) >> { >> int i; >> const char *final_commit_name = NULL; >> @@ -2445,7 +2445,7 @@ static const char *prepare_initial(struct scoreboard *sb) >> } >> if (!final_commit_name) >> die("No commit to dig down to?"); >> - return final_commit_name; >> + return xstrdup(final_commit_name); >> } >> >> static int blame_copy_callback(const struct option *option, const char *arg, int unset) >> @@ -2489,7 +2489,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) >> struct origin *o; >> struct blame_entry *ent = NULL; >> long dashdash_pos, lno; >> - const char *final_commit_name = NULL; >> + char *final_commit_name = NULL; >> enum object_type type; >> >> static struct string_list range_list; >> @@ -2786,6 +2786,8 @@ parse_done: >> >> assign_blame(&sb, opt); >> >> + free(final_commit_name); >> + >> if (incremental) >> return 0; -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html