object-name: free leaking object contexts

While it is documented in `struct object_context::path` that this
variable needs to be released by the caller, this fact is rather easy to
miss given that we do not ever provide a function to release the object
context. And of course, while some callers dutifully release the path,
many others don't.

Introduce a new `object_context_release()` function that releases the
path. Convert callsites that used to free the path to use that new
function and add missing calls to callsites that were leaking memory.
Refactor those callsites as required to have a single return path, only.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Patrick Steinhardt
2024-06-11 11:19:59 +02:00
committed by Junio C Hamano
parent 61f8bb1ec1
commit f87c55c264
11 changed files with 97 additions and 47 deletions

View File

@ -2130,30 +2130,26 @@ static int handle_dotdot(const char *arg,
struct rev_info *revs, int flags,
int cant_be_filename)
{
struct object_context a_oc, b_oc;
struct object_context a_oc = {0}, b_oc = {0};
char *dotdot = strstr(arg, "..");
int ret;
if (!dotdot)
return -1;
memset(&a_oc, 0, sizeof(a_oc));
memset(&b_oc, 0, sizeof(b_oc));
*dotdot = '\0';
ret = handle_dotdot_1(arg, dotdot, revs, flags, cant_be_filename,
&a_oc, &b_oc);
*dotdot = '.';
free(a_oc.path);
free(b_oc.path);
object_context_release(&a_oc);
object_context_release(&b_oc);
return ret;
}
static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int flags, unsigned revarg_opt)
{
struct object_context oc;
struct object_context oc = {0};
char *mark;
struct object *object;
struct object_id oid;
@ -2161,6 +2157,7 @@ static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int fl
const char *arg = arg_;
int cant_be_filename = revarg_opt & REVARG_CANNOT_BE_FILENAME;
unsigned get_sha1_flags = GET_OID_RECORD_PATH;
int ret;
flags = flags & UNINTERESTING ? flags | BOTTOM : flags & ~BOTTOM;
@ -2169,17 +2166,22 @@ static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int fl
* Just ".."? That is not a range but the
* pathspec for the parent directory.
*/
return -1;
ret = -1;
goto out;
}
if (!handle_dotdot(arg, revs, flags, revarg_opt))
return 0;
if (!handle_dotdot(arg, revs, flags, revarg_opt)) {
ret = 0;
goto out;
}
mark = strstr(arg, "^@");
if (mark && !mark[2]) {
*mark = 0;
if (add_parents_only(revs, arg, flags, 0))
return 0;
if (add_parents_only(revs, arg, flags, 0)) {
ret = 0;
goto out;
}
*mark = '^';
}
mark = strstr(arg, "^!");
@ -2194,8 +2196,10 @@ static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int fl
if (mark[2]) {
if (strtol_i(mark + 2, 10, &exclude_parent) ||
exclude_parent < 1)
return -1;
exclude_parent < 1) {
ret = -1;
goto out;
}
}
*mark = 0;
@ -2217,17 +2221,25 @@ static int handle_revision_arg_1(const char *arg_, struct rev_info *revs, int fl
* should error out if we can't even get an oid, as
* `--missing=print` should be able to report missing oids.
*/
if (get_oid_with_context(revs->repo, arg, get_sha1_flags, &oid, &oc))
return revs->ignore_missing ? 0 : -1;
if (get_oid_with_context(revs->repo, arg, get_sha1_flags, &oid, &oc)) {
ret = revs->ignore_missing ? 0 : -1;
goto out;
}
if (!cant_be_filename)
verify_non_filename(revs->prefix, arg);
object = get_reference(revs, arg, &oid, flags ^ local_flags);
if (!object)
return (revs->ignore_missing || revs->do_not_die_on_missing_objects) ? 0 : -1;
if (!object) {
ret = (revs->ignore_missing || revs->do_not_die_on_missing_objects) ? 0 : -1;
goto out;
}
add_rev_cmdline(revs, object, arg_, REV_CMD_REV, flags ^ local_flags);
add_pending_object_with_path(revs, object, arg, oc.mode, oc.path);
free(oc.path);
return 0;
ret = 0;
out:
object_context_release(&oc);
return ret;
}
int handle_revision_arg(const char *arg, struct rev_info *revs, int flags, unsigned revarg_opt)
@ -3062,6 +3074,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
diagnose_missing_default(revs->def);
object = get_reference(revs, revs->def, &oid, 0);
add_pending_object_with_mode(revs, object, revs->def, oc.mode);
object_context_release(&oc);
}
/* Did the user ask for any diff output? Run the diff! */