Add a semantic patch for converting certain calls of memcpy(3) to
COPY_ARRAY() and apply that transformation to the code base.  The result
is
 shorter and safer code.  For now only consider calls where source and
destination have the same type, or in other words: easy cases.

Signed-off-by: Rene Scharfe <l....@web.de>
---
 builtin/mv.c                   |  2 +-
 commit.c                       |  2 +-
 contrib/coccinelle/array.cocci | 26 ++++++++++++++++++++++++++
 pack-revindex.c                |  2 +-
 pathspec.c                     |  3 +--
 split-index.c                  |  6 ++----
 6 files changed, 32 insertions(+), 9 deletions(-)
 create mode 100644 contrib/coccinelle/array.cocci

diff --git a/builtin/mv.c b/builtin/mv.c
index 446a316..2f43877 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -26,7 +26,7 @@ static const char **internal_copy_pathspec(const char *prefix,
        int i;
        const char **result;
        ALLOC_ARRAY(result, count + 1);
-       memcpy(result, pathspec, count * sizeof(const char *));
+       COPY_ARRAY(result, pathspec, count);
        result[count] = NULL;
        for (i = 0; i < count; i++) {
                int length = strlen(result[i]);
diff --git a/commit.c b/commit.c
index ba6dee3..aada266 100644
--- a/commit.c
+++ b/commit.c
@@ -931,7 +931,7 @@ static int remove_redundant(struct commit **array, int cnt)
        }
 
        /* Now collect the result */
-       memcpy(work, array, sizeof(*array) * cnt);
+       COPY_ARRAY(work, array, cnt);
        for (i = filled = 0; i < cnt; i++)
                if (!redundant[i])
                        array[filled++] = work[i];
diff --git a/contrib/coccinelle/array.cocci b/contrib/coccinelle/array.cocci
new file mode 100644
index 0000000..2d7f25d
--- /dev/null
+++ b/contrib/coccinelle/array.cocci
@@ -0,0 +1,26 @@
+@@
+type T;
+T *dst;
+T *src;
+expression n;
+@@
+- memcpy(dst, src, n * sizeof(*dst));
++ COPY_ARRAY(dst, src, n);
+
+@@
+type T;
+T *dst;
+T *src;
+expression n;
+@@
+- memcpy(dst, src, n * sizeof(*src));
++ COPY_ARRAY(dst, src, n);
+
+@@
+type T;
+T *dst;
+T *src;
+expression n;
+@@
+- memcpy(dst, src, n * sizeof(T));
++ COPY_ARRAY(dst, src, n);
diff --git a/pack-revindex.c b/pack-revindex.c
index 96d51c3..6bc7c94 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -107,7 +107,7 @@ static void sort_revindex(struct revindex_entry *entries, 
unsigned n, off_t max)
         * we have to move it back from the temporary storage.
         */
        if (from != entries)
-               memcpy(entries, tmp, n * sizeof(*entries));
+               COPY_ARRAY(entries, tmp, n);
        free(tmp);
        free(pos);
 
diff --git a/pathspec.c b/pathspec.c
index 24e0dd5..49a5360 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -485,8 +485,7 @@ void copy_pathspec(struct pathspec *dst, const struct 
pathspec *src)
 {
        *dst = *src;
        ALLOC_ARRAY(dst->items, dst->nr);
-       memcpy(dst->items, src->items,
-              sizeof(struct pathspec_item) * dst->nr);
+       COPY_ARRAY(dst->items, src->items, dst->nr);
 }
 
 void clear_pathspec(struct pathspec *pathspec)
diff --git a/split-index.c b/split-index.c
index 3c75d4b..35da553 100644
--- a/split-index.c
+++ b/split-index.c
@@ -83,8 +83,7 @@ void move_cache_to_base_index(struct index_state *istate)
        si->base->timestamp = istate->timestamp;
        ALLOC_GROW(si->base->cache, istate->cache_nr, si->base->cache_alloc);
        si->base->cache_nr = istate->cache_nr;
-       memcpy(si->base->cache, istate->cache,
-              sizeof(*istate->cache) * istate->cache_nr);
+       COPY_ARRAY(si->base->cache, istate->cache, istate->cache_nr);
        mark_base_index_entries(si->base);
        for (i = 0; i < si->base->cache_nr; i++)
                si->base->cache[i]->ce_flags &= ~CE_UPDATE_IN_BASE;
@@ -141,8 +140,7 @@ void merge_base_index(struct index_state *istate)
        istate->cache       = NULL;
        istate->cache_alloc = 0;
        ALLOC_GROW(istate->cache, istate->cache_nr, istate->cache_alloc);
-       memcpy(istate->cache, si->base->cache,
-              sizeof(*istate->cache) * istate->cache_nr);
+       COPY_ARRAY(istate->cache, si->base->cache, istate->cache_nr);
 
        si->nr_deletions = 0;
        si->nr_replacements = 0;
-- 
2.10.0

Reply via email to