{"thread":{"id":"60891","subject":"[PATCH] use xstrncmpz()","startedAt":"2024-02-10T07:43:03Z","lastAt":"2024-02-10T07:43:03Z","messageCount":1,"participants":["René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"488333","messageId":"954b75d0-1504-4f57-b34e-e770a4b7b3ea@web.de","threadId":"60891","inReplyTo":null,"subject":"[PATCH] use xstrncmpz()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2024-02-10T07:43:01Z","receivedAt":"2024-02-10T07:43:03Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add and apply a semantic patch for calling xstrncmpz() to compare a\nNUL-terminated string with a buffer of a known length instead of using\nstrncmp() and checking the terminating NUL explicitly.  This simplifies\ncallers by reducing code duplication.\n\nI had to adjust remote.c manually because Coccinelle inexplicably\nchanged the indent of the else branches.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n archive-tar.c                      |  2 +-\n builtin/fast-export.c              |  3 +--\n builtin/merge.c                    |  3 +--\n builtin/reflog.c                   |  3 +--\n contrib/coccinelle/xstrncmpz.cocci | 28 ++++++++++++++++++++++++++++\n convert.c                          |  2 +-\n merge-ll.c                         |  2 +-\n object.c                           |  3 +--\n remote.c                           |  5 ++---\n userdiff.c                         |  3 +--\n 10 files changed, 38 insertions(+), 16 deletions(-)\n create mode 100644 contrib/coccinelle/xstrncmpz.cocci\n\ndiff --git a/archive-tar.c b/archive-tar.c\nindex f2a0ed7752..8ae30125f8 100644\n--- a/archive-tar.c\n+++ b/archive-tar.c\n@@ -365,7 +365,7 @@ static struct archiver *find_tar_filter(const char *name, size_t len)\n \tint i;\n \tfor (i = 0; i < nr_tar_filters; i++) {\n \t\tstruct archiver *ar = tar_filters[i];\n-\t\tif (!strncmp(ar->name, name, len) && !ar->name[len])\n+\t\tif (!xstrncmpz(ar->name, name, len))\n \t\t\treturn ar;\n \t}\n \treturn NULL;\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex f18f0809f9..4693d18cc9 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -136,8 +136,7 @@ static int anonymized_entry_cmp(const void *cmp_data UNUSED,\n \ta = container_of(eptr, const struct anonymized_entry, hash);\n \tif (keydata) {\n \t\tconst struct anonymized_entry_key *key = keydata;\n-\t\tint equal = !strncmp(a->orig, key->orig, key->orig_len) &&\n-\t\t\t    !a->orig[key->orig_len];\n+\t\tint equal = !xstrncmpz(a->orig, key->orig, key->orig_len);\n \t\treturn !equal;\n \t}\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 8f819781cc..935c8a57dd 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -192,8 +192,7 @@ static struct strategy *get_strategy(const char *name)\n \t\t\tint j, found = 0;\n \t\t\tstruct cmdname *ent = main_cmds.names[i];\n \t\t\tfor (j = 0; !found && j < ARRAY_SIZE(all_strategy); j++)\n-\t\t\t\tif (!strncmp(ent->name, all_strategy[j].name, ent->len)\n-\t\t\t\t\t\t&& !all_strategy[j].name[ent->len])\n+\t\t\t\tif (!xstrncmpz(all_strategy[j].name, ent->name, ent->len))\n \t\t\t\t\tfound = 1;\n \t\t\tif (!found)\n \t\t\t\tadd_cmdname(&not_strategies, ent->name, ent->len);\ndiff --git a/builtin/reflog.c b/builtin/reflog.c\nindex a5a4099f61..2c3369fca5 100644\n--- a/builtin/reflog.c\n+++ b/builtin/reflog.c\n@@ -96,8 +96,7 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)\n \t\treflog_expire_cfg_tail = &reflog_expire_cfg;\n\n \tfor (ent = reflog_expire_cfg; ent; ent = ent->next)\n-\t\tif (!strncmp(ent->pattern, pattern, len) &&\n-\t\t    ent->pattern[len] == '\\0')\n+\t\tif (!xstrncmpz(ent->pattern, pattern, len))\n \t\t\treturn ent;\n\n \tFLEX_ALLOC_MEM(ent, pattern, pattern, len);\ndiff --git a/contrib/coccinelle/xstrncmpz.cocci b/contrib/coccinelle/xstrncmpz.cocci\nnew file mode 100644\nindex 0000000000..ccb39e2bc0\n--- /dev/null\n+++ b/contrib/coccinelle/xstrncmpz.cocci\n@@ -0,0 +1,28 @@\n+@@\n+expression S, T, L;\n+@@\n+(\n+- strncmp(S, T, L) || S[L]\n++ !!xstrncmpz(S, T, L)\n+|\n+- strncmp(S, T, L) || S[L] != '\\0'\n++ !!xstrncmpz(S, T, L)\n+|\n+- strncmp(S, T, L) || T[L]\n++ !!xstrncmpz(T, S, L)\n+|\n+- strncmp(S, T, L) || T[L] != '\\0'\n++ !!xstrncmpz(T, S, L)\n+|\n+- !strncmp(S, T, L) && !S[L]\n++ !xstrncmpz(S, T, L)\n+|\n+- !strncmp(S, T, L) && S[L] == '\\0'\n++ !xstrncmpz(S, T, L)\n+|\n+- !strncmp(S, T, L) && !T[L]\n++ !xstrncmpz(T, S, L)\n+|\n+- !strncmp(S, T, L) && T[L] == '\\0'\n++ !xstrncmpz(T, S, L)\n+)\ndiff --git a/convert.c b/convert.c\nindex a8870baff3..35b25eb3cb 100644\n--- a/convert.c\n+++ b/convert.c\n@@ -1028,7 +1028,7 @@ static int read_convert_config(const char *var, const char *value,\n \tif (parse_config_key(var, \"filter\", &name, &namelen, &key) < 0 || !name)\n \t\treturn 0;\n \tfor (drv = user_convert; drv; drv = drv->next)\n-\t\tif (!strncmp(drv->name, name, namelen) && !drv->name[namelen])\n+\t\tif (!xstrncmpz(drv->name, name, namelen))\n \t\t\tbreak;\n \tif (!drv) {\n \t\tCALLOC_ARRAY(drv, 1);\ndiff --git a/merge-ll.c b/merge-ll.c\nindex 5ffb045efb..61e0ae5398 100644\n--- a/merge-ll.c\n+++ b/merge-ll.c\n@@ -292,7 +292,7 @@ static int read_merge_config(const char *var, const char *value,\n \t * after seeing merge.<name>.var1.\n \t */\n \tfor (fn = ll_user_merge; fn; fn = fn->next)\n-\t\tif (!strncmp(fn->name, name, namelen) && !fn->name[namelen])\n+\t\tif (!xstrncmpz(fn->name, name, namelen))\n \t\t\tbreak;\n \tif (!fn) {\n \t\tCALLOC_ARRAY(fn, 1);\ndiff --git a/object.c b/object.c\nindex 2c61e4c862..e6a1c4d905 100644\n--- a/object.c\n+++ b/object.c\n@@ -47,8 +47,7 @@ int type_from_string_gently(const char *str, ssize_t len, int gentle)\n \t\tlen = strlen(str);\n\n \tfor (i = 1; i < ARRAY_SIZE(object_type_strings); i++)\n-\t\tif (!strncmp(str, object_type_strings[i], len) &&\n-\t\t    object_type_strings[i][len] == '\\0')\n+\t\tif (!xstrncmpz(object_type_strings[i], str, len))\n \t\t\treturn i;\n\n \tif (gentle)\ndiff --git a/remote.c b/remote.c\nindex e07b316eac..9090632e96 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -105,7 +105,7 @@ static int remotes_hash_cmp(const void *cmp_data UNUSED,\n \tb = container_of(entry_or_key, const struct remote, ent);\n\n \tif (key)\n-\t\treturn strncmp(a->name, key->str, key->len) || a->name[key->len];\n+\t\treturn !!xstrncmpz(a->name, key->str, key->len);\n \telse\n \t\treturn strcmp(a->name, b->name);\n }\n@@ -189,8 +189,7 @@ static int branches_hash_cmp(const void *cmp_data UNUSED,\n \tb = container_of(entry_or_key, const struct branch, ent);\n\n \tif (key)\n-\t\treturn strncmp(a->name, key->str, key->len) ||\n-\t\t       a->name[key->len];\n+\t\treturn !!xstrncmpz(a->name, key->str, key->len);\n \telse\n \t\treturn strcmp(a->name, b->name);\n }\ndiff --git a/userdiff.c b/userdiff.c\nindex e399543823..2b1dab2649 100644\n--- a/userdiff.c\n+++ b/userdiff.c\n@@ -323,8 +323,7 @@ static int userdiff_find_by_namelen_cb(struct userdiff_driver *driver,\n {\n \tstruct find_by_namelen_data *cb_data = priv;\n\n-\tif (!strncmp(driver->name, cb_data->name, cb_data->len) &&\n-\t    !driver->name[cb_data->len]) {\n+\tif (!xstrncmpz(driver->name, cb_data->name, cb_data->len)) {\n \t\tcb_data->driver = driver;\n \t\treturn 1; /* tell the caller to stop iterating */\n \t}\n--\n2.43.0\n"}]}