Skip to content

Commit 4f40f6c

Browse files
avargitster
authored andcommitted
cocci: add and apply a rule to find "unused" strbufs
Add a coccinelle rule to remove "struct strbuf" initialization followed by calling "strbuf_release()" function, without any uses of the strbuf in the same function. See the tests in contrib/coccinelle/tests/unused.{c,res} for what it's intended to find and replace. The inclusion of "contrib/scalar/scalar.c" is because "spatch" was manually run on it (we don't usually run spatch on contrib). Per the "buggy code" comment we also match a strbuf_init() before the xmalloc(), but we're not seeking to be so strict as to make checks that the compiler will catch for us redundant. Saying we'll match either "init" or "xmalloc" lines makes the rule simpler. Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7a9a10b commit 4f40f6c

File tree

7 files changed

+119
-10
lines changed

7 files changed

+119
-10
lines changed

builtin/fetch.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
11131113
struct fetch_head *fetch_head, struct worktree **worktrees)
11141114
{
11151115
int url_len, i, rc = 0;
1116-
struct strbuf note = STRBUF_INIT, err = STRBUF_INIT;
1116+
struct strbuf note = STRBUF_INIT;
11171117
const char *what, *kind;
11181118
struct ref *rm;
11191119
char *url;
@@ -1281,7 +1281,6 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
12811281

12821282
abort:
12831283
strbuf_release(&note);
1284-
strbuf_release(&err);
12851284
free(url);
12861285
return rc;
12871286
}

builtin/merge.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,6 @@ static void reset_hard(const struct object_id *oid, int verbose)
375375
static void restore_state(const struct object_id *head,
376376
const struct object_id *stash)
377377
{
378-
struct strbuf sb = STRBUF_INIT;
379378
const char *args[] = { "stash", "apply", NULL, NULL };
380379

381380
if (is_null_oid(stash))
@@ -391,7 +390,6 @@ static void restore_state(const struct object_id *head,
391390
*/
392391
run_command_v_opt(args, RUN_GIT_CMD);
393392

394-
strbuf_release(&sb);
395393
refresh_cache(REFRESH_QUIET);
396394
}
397395

@@ -502,7 +500,6 @@ static void merge_name(const char *remote, struct strbuf *msg)
502500
{
503501
struct commit *remote_head;
504502
struct object_id branch_head;
505-
struct strbuf buf = STRBUF_INIT;
506503
struct strbuf bname = STRBUF_INIT;
507504
struct merge_remote_desc *desc;
508505
const char *ptr;
@@ -590,7 +587,6 @@ static void merge_name(const char *remote, struct strbuf *msg)
590587
oid_to_hex(&remote_head->object.oid), remote);
591588
cleanup:
592589
free(found_ref);
593-
strbuf_release(&buf);
594590
strbuf_release(&bname);
595591
}
596592

contrib/coccinelle/tests/unused.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
void test_strbuf(void)
2+
{
3+
struct strbuf sb1 = STRBUF_INIT;
4+
struct strbuf sb2 = STRBUF_INIT;
5+
struct strbuf sb3 = STRBUF_INIT;
6+
struct strbuf sb4 = STRBUF_INIT;
7+
struct strbuf sb5;
8+
struct strbuf sb6 = { 0 };
9+
struct strbuf sb7 = STRBUF_INIT;
10+
struct strbuf sb8 = STRBUF_INIT;
11+
struct strbuf *sp1;
12+
struct strbuf *sp2;
13+
struct strbuf *sp3;
14+
struct strbuf *sp4 = xmalloc(sizeof(struct strbuf));
15+
struct strbuf *sp5 = xmalloc(sizeof(struct strbuf));
16+
struct strbuf *sp6 = xmalloc(sizeof(struct strbuf));
17+
struct strbuf *sp7;
18+
19+
strbuf_init(&sb5, 0);
20+
strbuf_init(sp1, 0);
21+
strbuf_init(sp2, 0);
22+
strbuf_init(sp3, 0);
23+
strbuf_init(sp4, 0);
24+
strbuf_init(sp5, 0);
25+
strbuf_init(sp6, 0);
26+
strbuf_init(sp7, 0);
27+
sp7 = xmalloc(sizeof(struct strbuf));
28+
29+
use_before(&sb3);
30+
use_as_str("%s", sb7.buf);
31+
use_as_str("%s", sp1->buf);
32+
use_as_str("%s", sp6->buf);
33+
pass_pp(&sp3);
34+
35+
strbuf_release(&sb1);
36+
strbuf_reset(&sb2);
37+
strbuf_release(&sb3);
38+
strbuf_release(&sb4);
39+
strbuf_release(&sb5);
40+
strbuf_release(&sb6);
41+
strbuf_release(&sb7);
42+
strbuf_release(sp1);
43+
strbuf_release(sp2);
44+
strbuf_release(sp3);
45+
strbuf_release(sp4);
46+
strbuf_release(sp5);
47+
strbuf_release(sp6);
48+
strbuf_release(sp7);
49+
50+
use_after(&sb4);
51+
52+
if (when_strict())
53+
return;
54+
strbuf_release(&sb8);
55+
}

contrib/coccinelle/tests/unused.res

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
void test_strbuf(void)
2+
{
3+
struct strbuf sb3 = STRBUF_INIT;
4+
struct strbuf sb4 = STRBUF_INIT;
5+
struct strbuf sb7 = STRBUF_INIT;
6+
struct strbuf *sp1;
7+
struct strbuf *sp3;
8+
struct strbuf *sp6 = xmalloc(sizeof(struct strbuf));
9+
strbuf_init(sp1, 0);
10+
strbuf_init(sp3, 0);
11+
strbuf_init(sp6, 0);
12+
13+
use_before(&sb3);
14+
use_as_str("%s", sb7.buf);
15+
use_as_str("%s", sp1->buf);
16+
use_as_str("%s", sp6->buf);
17+
pass_pp(&sp3);
18+
19+
strbuf_release(&sb3);
20+
strbuf_release(&sb4);
21+
strbuf_release(&sb7);
22+
strbuf_release(sp1);
23+
strbuf_release(sp3);
24+
strbuf_release(sp6);
25+
26+
use_after(&sb4);
27+
28+
if (when_strict())
29+
return;
30+
}

contrib/coccinelle/unused.cocci

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This rule finds sequences of "unused" declerations and uses of a
2+
// variable, where "unused" is defined to include only calling the
3+
// equivalent of alloc, init & free functions on the variable.
4+
@@
5+
type T;
6+
identifier I;
7+
constant INIT_MACRO =~ "^STRBUF_INIT$";
8+
identifier MALLOC1 =~ "^x?[mc]alloc$";
9+
identifier INIT_CALL1 =~ "^strbuf_init$";
10+
identifier REL1 =~ "^strbuf_(release|reset)$";
11+
@@
12+
13+
(
14+
- T I;
15+
|
16+
- T I = { 0 };
17+
|
18+
- T I = INIT_MACRO;
19+
|
20+
- T I = MALLOC1(...);
21+
)
22+
23+
<... when != \( I \| &I \)
24+
(
25+
- \( INIT_CALL1 \)( \( I \| &I \), ...);
26+
|
27+
- I = MALLOC1(...);
28+
)
29+
...>
30+
31+
- \( REL1 \)( \( &I \| I \) );
32+
... when != \( I \| &I \)

contrib/scalar/scalar.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,7 @@ static int cmd_diagnose(int argc, const char **argv)
687687
int stdout_fd = -1, archiver_fd = -1;
688688
time_t now = time(NULL);
689689
struct tm tm;
690-
struct strbuf path = STRBUF_INIT, buf = STRBUF_INIT;
690+
struct strbuf buf = STRBUF_INIT;
691691
int res = 0;
692692

693693
argc = parse_options(argc, argv, NULL, options,
@@ -779,7 +779,6 @@ static int cmd_diagnose(int argc, const char **argv)
779779
free(argv_copy);
780780
strvec_clear(&archiver_args);
781781
strbuf_release(&zip_path);
782-
strbuf_release(&path);
783782
strbuf_release(&buf);
784783

785784
return res;

diff.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,7 +1289,6 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
12891289
{
12901290
static const char *nneof = " No newline at end of file\n";
12911291
const char *context, *reset, *set, *set_sign, *meta, *fraginfo;
1292-
struct strbuf sb = STRBUF_INIT;
12931292

12941293
enum diff_symbol s = eds->s;
12951294
const char *line = eds->line;
@@ -1521,7 +1520,6 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
15211520
default:
15221521
BUG("unknown diff symbol");
15231522
}
1524-
strbuf_release(&sb);
15251523
}
15261524

15271525
static void emit_diff_symbol(struct diff_options *o, enum diff_symbol s,

0 commit comments

Comments
 (0)