threads / patch / 51323

patch, 2 partscoccinelle: use COPY_ARRAY for copying arrays

Subject: [PATCH 1/2] coccinelle: use COPY_ARRAY for copying arrays

## tl;dr

3 messages between Jun 15, 2019 and Jun 17, 2019. Diffs are folded; open one to read it.

replies: 2people: 2as markdown or json

René Scharfe· Jun 15, 2019, 18:32 UTC · lore

The current semantic patch for COPY_ARRAY transforms memcpy(3) calls on pointers, but Coccinelle distinguishes them from arrays. It already contains three rules to handle the options for sizeof (i.e. source, destination and type), and handling arrays as source and destination would require four times as many rules if we enumerated all cases.

We also don't handle array subscripts, and supporting that would increase the number of rules by another factor of four. (An isomorphism telling Coccinelle that "sizeof x[...]" is equivalent to "sizeof *x" would be nice..)

Support arrays and array subscripts, but keep the number of rules down by adding normalization steps: First turn array subscripts into derefences, then determine the types of expressions used with sizeof and replace them with these types, and then convert the different possible combinations of arrays and pointers with memcpy(3) to COPY_ARRAY.

Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
 contrib/coccinelle/array.cocci | 61 +++++++++++++++++++++++++---------
 1 file changed, 46 insertions(+), 15 deletions(-)
Show changes to contrib/coccinelle/array.cocci +46 −16
diff --git a/contrib/coccinelle/array.cocci b/contrib/coccinelle/array.cocci
index 01586821dc..46b8d2ee11 100644
--- a/contrib/coccinelle/array.cocci
+++ b/contrib/coccinelle/array.cocci
@@ -1,29 +1,60 @@
 @@
-type T;
-T *dst;
-T *src;
-expression n;
+expression dst, src, n, E;
 @@
-- memcpy(dst, src, (n) * sizeof(*dst));
-+ COPY_ARRAY(dst, src, n);
+  memcpy(dst, src, n * sizeof(
+- E[...]
++ *(E)
+  ))

 @@
 type T;
-T *dst;
-T *src;
-expression n;
+T *ptr;
+T[] arr;
+expression E, n;
 @@
-- memcpy(dst, src, (n) * sizeof(*src));
-+ COPY_ARRAY(dst, src, n);
+(
+  memcpy(ptr, E,
+- n * sizeof(*(ptr))
++ n * sizeof(T)
+  )
+|
+  memcpy(arr, E,
+- n * sizeof(*(arr))
++ n * sizeof(T)
+  )
+|
+  memcpy(E, ptr,
+- n * sizeof(*(ptr))
++ n * sizeof(T)
+  )
+|
+  memcpy(E, arr,
+- n * sizeof(*(arr))
++ n * sizeof(T)
+  )
+)

 @@
 type T;
-T *dst;
-T *src;
+T *dst_ptr;
+T *src_ptr;
+T[] dst_arr;
+T[] src_arr;
 expression n;
 @@
-- memcpy(dst, src, (n) * sizeof(T));
-+ COPY_ARRAY(dst, src, n);
+(
+- memcpy(dst_ptr, src_ptr, (n) * sizeof(T))
++ COPY_ARRAY(dst_ptr, src_ptr, n)
+|
+- memcpy(dst_ptr, src_arr, (n) * sizeof(T))
++ COPY_ARRAY(dst_ptr, src_arr, n)
+|
+- memcpy(dst_arr, src_ptr, (n) * sizeof(T))
++ COPY_ARRAY(dst_arr, src_ptr, n)
+|
+- memcpy(dst_arr, src_arr, (n) * sizeof(T))
++ COPY_ARRAY(dst_arr, src_arr, n)
+)

 @@
 type T;
--
2.22.0
René Scharfe· Jun 15, 2019, 18:36 UTC · re: René Scharfe · lore

[PATCH 2/2] use COPY_ARRAY for copying arrays

Convert calls of memcpy(3) to use COPY_ARRAY, which shortens and simplifies the code a bit.

Patch generated by Coccinelle and contrib/coccinelle/array.cocci.
Signed-off-by: Rene Scharfe <l.s.r@web.de>
---
 fast-import.c | 2 +-
 kwset.c       | 2 +-
 packfile.c    | 6 +++---
 pretty.c      | 4 ++--
 4 files changed, 7 insertions(+), 7 deletions(-)
Show changes to 4 files +7 −8

fast-import.c, kwset.c, packfile.c, pretty.c

diff --git a/fast-import.c b/fast-import.c
index 76a7bd3699..6dfdd6801c 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -644,7 +644,7 @@ static struct tree_content *grow_tree_content(
 	struct tree_content *r = new_tree_content(t->entry_count + amt);
 	r->entry_count = t->entry_count;
 	r->delta_depth = t->delta_depth;
-	memcpy(r->entries,t->entries,t->entry_count*sizeof(t->entries[0]));
+	COPY_ARRAY(r->entries, t->entries, t->entry_count);
 	release_tree_content(t);
 	return r;
 }
diff --git a/kwset.c b/kwset.c
index 4fb6455aca..090ffcafa2 100644
--- a/kwset.c
+++ b/kwset.c
@@ -475,7 +475,7 @@ kwsprep (kwset_t kws)
 	for (i = 0; i < NCHAR; ++i)
 	  kwset->next[i] = next[U(trans[i])];
       else
-	memcpy(kwset->next, next, NCHAR * sizeof(struct trie *));
+	COPY_ARRAY(kwset->next, next, NCHAR);
     }

   /* Fix things up for any translation table. */
diff --git a/packfile.c b/packfile.c
index d786ec7312..d55cb7f013 100644
--- a/packfile.c
+++ b/packfile.c
@@ -1269,7 +1269,7 @@ static enum object_type packed_to_object_type(struct repository *r,
 		if (poi_stack_nr >= poi_stack_alloc && poi_stack == small_poi_stack) {
 			poi_stack_alloc = alloc_nr(poi_stack_nr);
 			ALLOC_ARRAY(poi_stack, poi_stack_alloc);
-			memcpy(poi_stack, small_poi_stack, sizeof(off_t)*poi_stack_nr);
+			COPY_ARRAY(poi_stack, small_poi_stack, poi_stack_nr);
 		} else {
 			ALLOC_GROW(poi_stack, poi_stack_nr+1, poi_stack_alloc);
 		}
@@ -1679,8 +1679,8 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset,
 		    && delta_stack == small_delta_stack) {
 			delta_stack_alloc = alloc_nr(delta_stack_nr);
 			ALLOC_ARRAY(delta_stack, delta_stack_alloc);
-			memcpy(delta_stack, small_delta_stack,
-			       sizeof(*delta_stack)*delta_stack_nr);
+			COPY_ARRAY(delta_stack, small_delta_stack,
+				   delta_stack_nr);
 		} else {
 			ALLOC_GROW(delta_stack, delta_stack_nr+1, delta_stack_alloc);
 		}
diff --git a/pretty.c b/pretty.c
index ced0485257..e4ed14effe 100644
--- a/pretty.c
+++ b/pretty.c
@@ -106,8 +106,8 @@ static void setup_commit_formats(void)
 	commit_formats_len = ARRAY_SIZE(builtin_formats);
 	builtin_formats_len = commit_formats_len;
 	ALLOC_GROW(commit_formats, commit_formats_len, commit_formats_alloc);
-	memcpy(commit_formats, builtin_formats,
-	       sizeof(*builtin_formats)*ARRAY_SIZE(builtin_formats));
+	COPY_ARRAY(commit_formats, builtin_formats,
+		   ARRAY_SIZE(builtin_formats));

 	git_config(git_pretty_formats_config, NULL);
 }
--
2.22.0
Derrick Stolee· Jun 17, 2019, 01:14 UTC · re: René Scharfe · lore

Re: [PATCH 2/2] use COPY_ARRAY for copying arrays

On 6/15/2019 2:36 PM, René Scharfe wrote:
> Convert calls of memcpy(3) to use COPY_ARRAY, which shortens and
> simplifies the code a bit.
These changes do look simpler. Thanks!
> Patch generated by Coccinelle and contrib/coccinelle/array.cocci.
And this auto-generation is particularly useful!
Show 19 quoted lines
> 
> Signed-off-by: Rene Scharfe <l.s.r@web.de>
> ---
>  fast-import.c | 2 +-
>  kwset.c       | 2 +-
>  packfile.c    | 6 +++---
>  pretty.c      | 4 ++--
>  4 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/kwset.c b/kwset.c
> index 4fb6455aca..090ffcafa2 100644
> --- a/kwset.c
> +++ b/kwset.c
> @@ -475,7 +475,7 @@ kwsprep (kwset_t kws)
>  	for (i = 0; i < NCHAR; ++i)
>  	  kwset->next[i] = next[U(trans[i])];
>        else
> -	memcpy(kwset->next, next, NCHAR * sizeof(struct trie *));
> +	COPY_ARRAY(kwset->next, next, NCHAR);

I was unfamiliar with kwset.c, so I took a look and noticed that it was adapted from GNU grep, so this change takes us even farther from the original source (and closer to Git source conventions).

I think this is the right thing to do, but thought I'd point it out in case anyone thought differently.

Both patches LGTM.

Thanks, -Stolee

← back to recent threads