{"thread":{"id":"49604","subject":"[PATCH v2 2/3] ls-remote: release memory instead of UNLEAK","startedAt":"2018-10-18T07:28:57Z","lastAt":"2018-10-18T07:28:59Z","messageCount":3,"participants":["Olga Telezhnaya"],"isPatch":true,"patchVersion":2,"patchTotal":3},"messages":[{"id":"360825","messageId":"010201668613c46c-c42176a8-e4b9-4f31-a384-3ed9848377ef-000000@eu-west-1.amazonses.com","threadId":"49604","inReplyTo":"010201668613c3de-23d41696-1476-4949-9834-a31adeb0650e-000000@eu-west-1.amazonses.com","subject":"[PATCH v2 2/3] ls-remote: release memory instead of UNLEAK","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-10-18T07:28:54Z","receivedAt":"2018-10-18T07:28:57Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Use ref_array_clear() to release memory instead of UNLEAK macros.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n builtin/ls-remote.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/builtin/ls-remote.c b/builtin/ls-remote.c\nindex 1a25df7ee15b4..6a0cdec30d2d7 100644\n--- a/builtin/ls-remote.c\n+++ b/builtin/ls-remote.c\n@@ -151,6 +151,6 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t}\n \n \tUNLEAK(sorting);\n-\tUNLEAK(ref_array);\n+\tref_array_clear(&ref_array);\n \treturn status;\n }\n\n--\nhttps://github.com/git/git/pull/538\n"},{"id":"360826","messageId":"010201668613c3de-23d41696-1476-4949-9834-a31adeb0650e-000000@eu-west-1.amazonses.com","threadId":"49604","inReplyTo":"0102016657e7cfee-f1343b1e-9a85-4cae-990a-cc7177ea8487-000000@eu-west-1.amazonses.com","subject":"[PATCH v2 1/3] ref-filter: free memory from used_atom","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-10-18T07:28:54Z","receivedAt":"2018-10-18T07:28:57Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Release memory from used_atom variable for reducing number of memory\nleaks.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n ref-filter.c | 4 ++++\n 1 file changed, 4 insertions(+)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex e1bcb4ca8a197..70f1d13ab3beb 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1996,6 +1996,10 @@ void ref_array_clear(struct ref_array *array)\n {\n \tint i;\n \n+\tfor (i = 0; i < used_atom_cnt; i++)\n+\t\tfree((char *)used_atom[i].name);\n+\tFREE_AND_NULL(used_atom);\n+\tused_atom_cnt = 0;\n \tfor (i = 0; i < array->nr; i++)\n \t\tfree_array_item(array->items[i]);\n \tFREE_AND_NULL(array->items);\n\n--\nhttps://github.com/git/git/pull/538\n"},{"id":"360827","messageId":"010201668613c4dd-aa890c7f-39a9-4d01-b242-e38fb4ab9518-000000@eu-west-1.amazonses.com","threadId":"49604","inReplyTo":"010201668613c3de-23d41696-1476-4949-9834-a31adeb0650e-000000@eu-west-1.amazonses.com","subject":"[PATCH v2 3/3] ref-filter: free item->value and item->value->s","fromName":"Olga Telezhnaya","fromEmail":"olyatelezhnaya@gmail.com","sentAt":"2018-10-18T07:28:54Z","receivedAt":"2018-10-18T07:28:59Z","isPatch":true,"sender":{"key":"olyatelezhnaya@gmail.com","avatar":"https://avatars.githubusercontent.com/u/11246099?v=4"},"body":"Release item->value.\nInitialize item->value->s dynamically and then release its resources.\nRelease some local variables.\n\nFinal goal of this patch is to reduce number of memory leaks.\n\nSigned-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>\n---\n ref-filter.c | 96 +++++++++++++++++++++++++++++-----------------------\n 1 file changed, 54 insertions(+), 42 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 70f1d13ab3beb..ca52ee4608c2a 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -875,7 +875,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_\n \t\tif (deref)\n \t\t\tname++;\n \t\tif (!strcmp(name, \"objecttype\"))\n-\t\t\tv->s = type_name(oi->type);\n+\t\t\tv->s = xstrdup(type_name(oi->type));\n \t\telse if (!strcmp(name, \"objectsize\")) {\n \t\t\tv->value = oi->size;\n \t\t\tv->s = xstrfmt(\"%lu\", oi->size);\n@@ -899,9 +899,9 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob\n \t\tif (deref)\n \t\t\tname++;\n \t\tif (!strcmp(name, \"tag\"))\n-\t\t\tv->s = tag->tag;\n+\t\t\tv->s = xstrdup(tag->tag);\n \t\telse if (!strcmp(name, \"type\") && tag->tagged)\n-\t\t\tv->s = type_name(tag->tagged->type);\n+\t\t\tv->s = xstrdup(type_name(tag->tagged->type));\n \t\telse if (!strcmp(name, \"object\") && tag->tagged)\n \t\t\tv->s = xstrdup(oid_to_hex(&tag->tagged->oid));\n \t}\n@@ -1032,7 +1032,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam\n \tv->value = timestamp;\n \treturn;\n  bad:\n-\tv->s = \"\";\n+\tv->s = xstrdup(\"\");\n \tv->value = 0;\n }\n \n@@ -1227,7 +1227,7 @@ static void fill_missing_values(struct atom_value *val)\n \tfor (i = 0; i < used_atom_cnt; i++) {\n \t\tstruct atom_value *v = &val[i];\n \t\tif (v->s == NULL)\n-\t\t\tv->s = \"\";\n+\t\t\tv->s = xstrdup(\"\");\n \t}\n }\n \n@@ -1273,7 +1273,8 @@ static inline char *copy_advance(char *dst, const char *src)\n static const char *lstrip_ref_components(const char *refname, int len)\n {\n \tlong remaining = len;\n-\tconst char *start = refname;\n+\tconst char *start = xstrdup(refname);\n+\tconst char *to_free = start;\n \n \tif (len < 0) {\n \t\tint i;\n@@ -1294,20 +1295,24 @@ static const char *lstrip_ref_components(const char *refname, int len)\n \twhile (remaining > 0) {\n \t\tswitch (*start++) {\n \t\tcase '\\0':\n-\t\t\treturn \"\";\n+\t\t\tfree((char *)to_free);\n+\t\t\treturn xstrdup(\"\");\n \t\tcase '/':\n \t\t\tremaining--;\n \t\t\tbreak;\n \t\t}\n \t}\n \n+\tstart = xstrdup(start);\n+\tfree((char *)to_free);\n \treturn start;\n }\n \n static const char *rstrip_ref_components(const char *refname, int len)\n {\n \tlong remaining = len;\n-\tchar *start = xstrdup(refname);\n+\tconst char *start = xstrdup(refname);\n+\tconst char *to_free = start;\n \n \tif (len < 0) {\n \t\tint i;\n@@ -1327,9 +1332,10 @@ static const char *rstrip_ref_components(const char *refname, int len)\n \n \twhile (remaining-- > 0) {\n \t\tchar *p = strrchr(start, '/');\n-\t\tif (p == NULL)\n-\t\t\treturn \"\";\n-\t\telse\n+\t\tif (p == NULL) {\n+\t\t\tfree((char *)to_free);\n+\t\t\treturn xstrdup(\"\");\n+\t\t} else\n \t\t\tp[0] = '\\0';\n \t}\n \treturn start;\n@@ -1344,7 +1350,7 @@ static const char *show_ref(struct refname_atom *atom, const char *refname)\n \telse if (atom->option == R_RSTRIP)\n \t\treturn rstrip_ref_components(refname, atom->rstrip);\n \telse\n-\t\treturn refname;\n+\t\treturn xstrdup(refname);\n }\n \n static void fill_remote_ref_details(struct used_atom *atom, const char *refname,\n@@ -1358,7 +1364,7 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,\n \t\t\t\t       NULL, AHEAD_BEHIND_FULL) < 0) {\n \t\t\t*s = xstrdup(msgs.gone);\n \t\t} else if (!num_ours && !num_theirs)\n-\t\t\t*s = \"\";\n+\t\t\t*s = xstrdup(\"\");\n \t\telse if (!num_ours)\n \t\t\t*s = xstrfmt(msgs.behind, num_theirs);\n \t\telse if (!num_theirs)\n@@ -1373,36 +1379,31 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname,\n \t\t}\n \t} else if (atom->u.remote_ref.option == RR_TRACKSHORT) {\n \t\tif (stat_tracking_info(branch, &num_ours, &num_theirs,\n-\t\t\t\t       NULL, AHEAD_BEHIND_FULL) < 0)\n+\t\t\t\t       NULL, AHEAD_BEHIND_FULL) < 0) {\n+\t\t\t*s = xstrdup(\"\");\n \t\t\treturn;\n-\n+\t\t}\n \t\tif (!num_ours && !num_theirs)\n-\t\t\t*s = \"=\";\n+\t\t\t*s = xstrdup(\"=\");\n \t\telse if (!num_ours)\n-\t\t\t*s = \"<\";\n+\t\t\t*s = xstrdup(\"<\");\n \t\telse if (!num_theirs)\n-\t\t\t*s = \">\";\n+\t\t\t*s = xstrdup(\">\");\n \t\telse\n-\t\t\t*s = \"<>\";\n+\t\t\t*s = xstrdup(\"<>\");\n \t} else if (atom->u.remote_ref.option == RR_REMOTE_NAME) {\n \t\tint explicit;\n \t\tconst char *remote = atom->u.remote_ref.push ?\n \t\t\tpushremote_for_branch(branch, &explicit) :\n \t\t\tremote_for_branch(branch, &explicit);\n-\t\tif (explicit)\n-\t\t\t*s = xstrdup(remote);\n-\t\telse\n-\t\t\t*s = \"\";\n+\t\t*s = xstrdup(explicit ? remote : \"\");\n \t} else if (atom->u.remote_ref.option == RR_REMOTE_REF) {\n \t\tint explicit;\n \t\tconst char *merge;\n \n \t\tmerge = remote_ref_for_branch(branch, atom->u.remote_ref.push,\n \t\t\t\t\t      &explicit);\n-\t\tif (explicit)\n-\t\t\t*s = xstrdup(merge);\n-\t\telse\n-\t\t\t*s = \"\";\n+\t\t*s = xstrdup(explicit ? merge : \"\");\n \t} else\n \t\tBUG(\"unhandled RR_* enum\");\n }\n@@ -1451,7 +1452,7 @@ char *get_head_description(void)\n static const char *get_symref(struct used_atom *atom, struct ref_array_item *ref)\n {\n \tif (!ref->symref)\n-\t\treturn \"\";\n+\t\treturn xstrdup(\"\");\n \telse\n \t\treturn show_ref(&atom->u.refname, ref->symref);\n }\n@@ -1510,7 +1511,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\tref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,\n \t\t\t\t\t     NULL, NULL);\n \t\tif (!ref->symref)\n-\t\t\tref->symref = \"\";\n+\t\t\tref->symref = xstrdup(\"\");\n \t}\n \n \t/* Fill in specials first */\n@@ -1536,20 +1537,23 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t\trefname = get_symref(atom, ref);\n \t\telse if (starts_with(name, \"upstream\")) {\n \t\t\tconst char *branch_name;\n-\t\t\tv->s = \"\";\n \t\t\t/* only local branches may have an upstream */\n \t\t\tif (!skip_prefix(ref->refname, \"refs/heads/\",\n-\t\t\t\t\t &branch_name))\n+\t\t\t\t\t &branch_name)) {\n+\t\t\t\tv->s = xstrdup(\"\");\n \t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tbranch = branch_get(branch_name);\n \n \t\t\trefname = branch_get_upstream(branch, NULL);\n \t\t\tif (refname)\n \t\t\t\tfill_remote_ref_details(atom, refname, branch, &v->s);\n+\t\t\telse\n+\t\t\t\tv->s = xstrdup(\"\");\n \t\t\tcontinue;\n \t\t} else if (atom->u.remote_ref.push) {\n \t\t\tconst char *branch_name;\n-\t\t\tv->s = \"\";\n+\t\t\tv->s = xstrdup(\"\");\n \t\t\tif (!skip_prefix(ref->refname, \"refs/heads/\",\n \t\t\t\t\t &branch_name))\n \t\t\t\tcontinue;\n@@ -1562,10 +1566,12 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t\t\tif (!refname)\n \t\t\t\t\tcontinue;\n \t\t\t}\n+\t\t\t/* We will definitely re-init v->s on the next line. */\n+\t\t\tfree((char *)v->s);\n \t\t\tfill_remote_ref_details(atom, refname, branch, &v->s);\n \t\t\tcontinue;\n \t\t} else if (starts_with(name, \"color:\")) {\n-\t\t\tv->s = atom->u.color;\n+\t\t\tv->s = xstrdup(atom->u.color);\n \t\t\tcontinue;\n \t\t} else if (!strcmp(name, \"flag\")) {\n \t\t\tchar buf[256], *cp = buf;\n@@ -1574,7 +1580,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t\tif (ref->flag & REF_ISPACKED)\n \t\t\t\tcp = copy_advance(cp, \",packed\");\n \t\t\tif (cp == buf)\n-\t\t\t\tv->s = \"\";\n+\t\t\t\tv->s = xstrdup(\"\");\n \t\t\telse {\n \t\t\t\t*cp = '\\0';\n \t\t\t\tv->s = xstrdup(buf + 1);\n@@ -1584,40 +1590,42 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t\tcontinue;\n \t\t} else if (!strcmp(name, \"HEAD\")) {\n \t\t\tif (atom->u.head && !strcmp(ref->refname, atom->u.head))\n-\t\t\t\tv->s = \"*\";\n+\t\t\t\tv->s = xstrdup(\"*\");\n \t\t\telse\n-\t\t\t\tv->s = \" \";\n+\t\t\t\tv->s = xstrdup(\" \");\n \t\t\tcontinue;\n \t\t} else if (starts_with(name, \"align\")) {\n \t\t\tv->handler = align_atom_handler;\n-\t\t\tv->s = \"\";\n+\t\t\tv->s = xstrdup(\"\");\n \t\t\tcontinue;\n \t\t} else if (!strcmp(name, \"end\")) {\n \t\t\tv->handler = end_atom_handler;\n-\t\t\tv->s = \"\";\n+\t\t\tv->s = xstrdup(\"\");\n \t\t\tcontinue;\n \t\t} else if (starts_with(name, \"if\")) {\n \t\t\tconst char *s;\n-\t\t\tv->s = \"\";\n \t\t\tif (skip_prefix(name, \"if:\", &s))\n \t\t\t\tv->s = xstrdup(s);\n+\t\t\telse\n+\t\t\t\tv->s = xstrdup(\"\");\n \t\t\tv->handler = if_atom_handler;\n \t\t\tcontinue;\n \t\t} else if (!strcmp(name, \"then\")) {\n \t\t\tv->handler = then_atom_handler;\n-\t\t\tv->s = \"\";\n+\t\t\tv->s = xstrdup(\"\");\n \t\t\tcontinue;\n \t\t} else if (!strcmp(name, \"else\")) {\n \t\t\tv->handler = else_atom_handler;\n-\t\t\tv->s = \"\";\n+\t\t\tv->s = xstrdup(\"\");\n \t\t\tcontinue;\n \t\t} else\n \t\t\tcontinue;\n \n \t\tif (!deref)\n-\t\t\tv->s = refname;\n+\t\t\tv->s = xstrdup(refname);\n \t\telse\n \t\t\tv->s = xstrfmt(\"%s^{}\", refname);\n+\t\tfree((char *)refname);\n \t}\n \n \tfor (i = 0; i < used_atom_cnt; i++) {\n@@ -1988,6 +1996,10 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,\n static void free_array_item(struct ref_array_item *item)\n {\n \tfree((char *)item->symref);\n+\tif (item->value) {\n+\t\tfree((char *)item->value->s);\n+\t\tfree(item->value);\n+\t}\n \tfree(item);\n }\n \n\n--\nhttps://github.com/git/git/pull/538\n"}]}