Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PATCH] Use C_ARRAY_LENGTH and C_ARRAY_END #13796

Closed
p5pRT opened this issue May 2, 2014 · 14 comments
Closed

[PATCH] Use C_ARRAY_LENGTH and C_ARRAY_END #13796

p5pRT opened this issue May 2, 2014 · 14 comments
Labels

Comments

@p5pRT
Copy link

p5pRT commented May 2, 2014

Migrated from rt.perl.org#121786 (status was 'resolved')

Searchable as RT121786$

@p5pRT
Copy link
Author

p5pRT commented May 2, 2014

From @jhi

Use C_ARRAY_LENGTH and C_ARRAY_END.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found potential off-by-one error in sv.c​:Perl_sv_magic​:
how > C_ARRAY_LENGTH(PL_magic_data)
should probably have been
how >= C_ARRAY_LENGTH(PL_magic_data)
No tests fail, but this seems to be more of an internal sanity check.

@p5pRT
Copy link
Author

p5pRT commented May 2, 2014

From @jhi

0001-Use-C_ARRAY_LENGTH-and-C_ARRAY_END.patch
From 86696cfff6b7a222bf2475fcdb06ccfe0eafb357 Mon Sep 17 00:00:00 2001
From: Jarkko Hietaniemi <jhi@iki.fi>
Date: Fri, 2 May 2014 08:54:26 -0400
Subject: [PATCH] Use C_ARRAY_LENGTH and C_ARRAY_END.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found potential off-by-one error in sv.c:Perl_sv_magic:
how > C_ARRAY_LENGTH(PL_magic_data)
should probably have been
how >= C_ARRAY_LENGTH(PL_magic_data)
No tests fail, but this seems to be more of an internal sanity check.
---
 dump.c       | 5 ++---
 handy.h      | 7 ++++++-
 patchlevel.h | 2 +-
 perl.c       | 2 +-
 sv.c         | 5 ++---
 universal.c  | 3 +--
 util.c       | 4 ++--
 7 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/dump.c b/dump.c
index 354cd57..59be3e0 100644
--- a/dump.c
+++ b/dump.c
@@ -868,8 +868,7 @@ const struct op_private_by_op op_private_names[] = {
 static bool
 S_op_private_to_names(pTHX_ SV *tmpsv, U32 optype, U32 op_private) {
     const struct op_private_by_op *start = op_private_names;
-    const struct op_private_by_op *const end
-	= op_private_names + C_ARRAY_LENGTH(op_private_names);
+    const struct op_private_by_op *const end = C_ARRAY_END(op_private_names);
 
     /* This is a linear search, but no worse than the code that it replaced.
        It's debugging code - size is more important than speed.  */
@@ -1894,7 +1893,7 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo
 	if (HvARRAY(sv) && usedkeys) {
 	    /* Show distribution of HEs in the ARRAY */
 	    int freq[200];
-#define FREQ_MAX ((int)(sizeof freq / sizeof freq[0] - 1))
+#define FREQ_MAX ((int)(C_ARRAY_LENGTH(freq) - 1))
 	    int i;
 	    int max = 0;
 	    U32 pow2 = 2, keys = usedkeys;
diff --git a/handy.h b/handy.h
index 3f84eff..3f2f394 100644
--- a/handy.h
+++ b/handy.h
@@ -1936,8 +1936,13 @@ void Perl_mem_log_del_sv(const SV *sv, const char *filename, const int linenumbe
 #define StructCopy(s,d,t) Copy(s,d,1,t)
 #endif
 
+/* C_ARRAY_LENGTH is the number of elements in the C array (so you
+ * want your zero-based indices to be less than but not equal to).
+ *
+ * C_ARRAY_END is one past the last: half-open/half-closed range,
+ * not last-inclusive range. */
 #define C_ARRAY_LENGTH(a)	(sizeof(a)/sizeof((a)[0]))
-#define C_ARRAY_END(a)		(a) + (sizeof(a)/sizeof((a)[0]))
+#define C_ARRAY_END(a)		((a) + (sizeof(a)/sizeof((a)[0])))
 
 #ifdef NEED_VA_COPY
 # ifdef va_copy
diff --git a/patchlevel.h b/patchlevel.h
index 6567b2f..acd8925 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -144,7 +144,7 @@ static const char * const local_patches[] = {
 
 /* Initial space prevents this variable from being inserted in config.sh  */
 #  define	LOCAL_PATCH_COUNT	\
-	((int)(sizeof(local_patches)/sizeof(local_patches[0])-2))
+	((int)(C_ARRAY_LENGTH(local_patches)-2))
 
 /* the old terms of reference, add them only when explicitly included */
 #define PATCHLEVEL		PERL_VERSION
diff --git a/perl.c b/perl.c
index f5007f7..023748c 100644
--- a/perl.c
+++ b/perl.c
@@ -677,7 +677,7 @@ perl_destruct(pTHXx)
 		msg.msg_name = NULL;
 		msg.msg_namelen = 0;
 		msg.msg_iov = vec;
-		msg.msg_iovlen = sizeof(vec)/sizeof(vec[0]);
+		msg.msg_iovlen = C_ARRAY_LENGTH(vec);
 
 		vec[0].iov_base = (void*)&target;
 		vec[0].iov_len = sizeof(target);
diff --git a/sv.c b/sv.c
index 85f91f1..971bf21 100644
--- a/sv.c
+++ b/sv.c
@@ -5557,7 +5557,7 @@ Perl_sv_magic(pTHX_ SV *const sv, SV *const obj, const int how,
 
     PERL_ARGS_ASSERT_SV_MAGIC;
 
-    if (how < 0 || (unsigned)how > C_ARRAY_LENGTH(PL_magic_data)
+    if (how < 0 || (unsigned)how >= C_ARRAY_LENGTH(PL_magic_data)
 	|| ((flags = PL_magic_data[how]),
 	    (vtable_index = flags & PERL_MAGIC_VTABLE_MASK)
 	    > magic_vtable_max))
@@ -12125,8 +12125,7 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *const tbl, const void *const oldsv, void *
 	    new_arena->next = tbl->tbl_arena;
 	    tbl->tbl_arena = new_arena;
 	    tbl->tbl_arena_next = new_arena->array;
-	    tbl->tbl_arena_end = new_arena->array
-		+ sizeof(new_arena->array) / sizeof(new_arena->array[0]);
+	    tbl->tbl_arena_end = C_ARRAY_END(new_arena->array);
 	}
 
 	tblent = tbl->tbl_arena_next++;
diff --git a/universal.c b/universal.c
index bccc8fb..a29696d 100644
--- a/universal.c
+++ b/universal.c
@@ -1059,8 +1059,7 @@ Perl_boot_core_UNIVERSAL(pTHX)
     dVAR;
     static const char file[] = __FILE__;
     const struct xsub_details *xsub = details;
-    const struct xsub_details *end
-	= details + sizeof(details) / sizeof(details[0]);
+    const struct xsub_details *end = C_ARRAY_END(details);
 
     do {
 	newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
diff --git a/util.c b/util.c
index 0a0ee40..b90abe5 100644
--- a/util.c
+++ b/util.c
@@ -4576,8 +4576,8 @@ Perl_init_global_struct(pTHX)
 {
     struct perl_vars *plvarsp = NULL;
 # ifdef PERL_GLOBAL_STRUCT
-    const IV nppaddr = sizeof(Gppaddr)/sizeof(Perl_ppaddr_t);
-    const IV ncheck  = sizeof(Gcheck) /sizeof(Perl_check_t);
+    const IV nppaddr = C_ARRAY_LENGTH(Gppaddr);
+    const IV ncheck  = C_ARRAY_LENGTH(Gcheck);
 #  ifdef PERL_GLOBAL_STRUCT_PRIVATE
     /* PerlMem_malloc() because can't use even safesysmalloc() this early. */
     plvarsp = (struct perl_vars*)PerlMem_malloc(sizeof(struct perl_vars));
-- 
1.9.2

@p5pRT
Copy link
Author

p5pRT commented May 3, 2014

From @shlomif

On Fri May 02 06​:02​:20 2014, jhi wrote​:

Use C_ARRAY_LENGTH and C_ARRAY_END.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found potential off-by-one error in sv.c​:Perl_sv_magic​:
how > C_ARRAY_LENGTH(PL_magic_data)
should probably have been
how >= C_ARRAY_LENGTH(PL_magic_data)
No tests fail, but this seems to be more of an internal sanity check.

Looks like a useful patch. Thanks!

@p5pRT
Copy link
Author

p5pRT commented May 3, 2014

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented May 6, 2014

From @tonycoz

On Fri May 02 06​:02​:20 2014, jhi wrote​:

Use C_ARRAY_LENGTH and C_ARRAY_END.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found potential off-by-one error in sv.c​:Perl_sv_magic​:
how > C_ARRAY_LENGTH(PL_magic_data)
should probably have been
how >= C_ARRAY_LENGTH(PL_magic_data)
No tests fail, but this seems to be more of an internal sanity check.

Looks good, added to 5.21.1 blockers.

Tony

@p5pRT
Copy link
Author

p5pRT commented May 10, 2014

From @bulk88

Is this Coverity or hand found issue? Just curious.

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented May 10, 2014

From @jhi

On Saturday-201405-10, 17​:20, bulk88 via RT wrote​:

Is this Coverity or hand found issue? Just curious.

Not Coverity-found as such, but "inspired", since first Coverity had
found at least... three? four? for-loops going over C arrays, where the
same one-past-the-array error happened (with easily statically
analyzable index limits).

And then I decided to inspect the code for similar spots, since I knew
we had the C_ARRAY_LENGTH that could be used.

And while I did that, I noticed that one spot where use of this macro
fixed probably a dormant bug (not a for-loop, though).

@p5pRT
Copy link
Author

p5pRT commented May 12, 2014

From @jhi

On Monday-201405-05, 20​:41, Tony Cook via RT wrote​:

On Fri May 02 06​:02​:20 2014, jhi wrote​:

Use C_ARRAY_LENGTH and C_ARRAY_END.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found potential off-by-one error in sv.c​:Perl_sv_magic​:
how > C_ARRAY_LENGTH(PL_magic_data)
should probably have been
how >= C_ARRAY_LENGTH(PL_magic_data)
No tests fail, but this seems to be more of an internal sanity check.

Looks good, added to 5.21.1 blockers.

Tony

Updated patch​: found one more spot in regcomp.c, and now using
C_ARRAY_LENGTH in the definition of C_ARRAY_END (duh)

@p5pRT
Copy link
Author

p5pRT commented May 12, 2014

From @jhi

0001-Use-C_ARRAY_LENGTH-and-C_ARRAY_END.patch
From b2f369a8bd74859d06a9315ffa208e3fbebb2099 Mon Sep 17 00:00:00 2001
From: Jarkko Hietaniemi <jhi@iki.fi>
Date: Fri, 2 May 2014 08:54:26 -0400
Subject: [PATCH] Use C_ARRAY_LENGTH and C_ARRAY_END.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found
(1) definite off-by-one error in regcomp.c:Perl_regprop
  if (index > (sizeof(anyofs) / sizeof(anyofs[0]))) {
  (for failure) needed to be
  if (index < C_ARRAY_LENGTH(anyofs)) {
(2) potential off-by-one error in sv.c:Perl_sv_magic:
  how > C_ARRAY_LENGTH(PL_magic_data)
  (for failure) should probably have been
  how >= C_ARRAY_LENGTH(PL_magic_data)
  No tests fail, but this seems to be more of an internal sanity check.
---
 dump.c       | 5 ++---
 handy.h      | 7 ++++++-
 patchlevel.h | 2 +-
 perl.c       | 2 +-
 regcomp.c    | 8 ++++----
 sv.c         | 5 ++---
 universal.c  | 3 +--
 util.c       | 4 ++--
 8 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/dump.c b/dump.c
index 354cd57..59be3e0 100644
--- a/dump.c
+++ b/dump.c
@@ -868,8 +868,7 @@ const struct op_private_by_op op_private_names[] = {
 static bool
 S_op_private_to_names(pTHX_ SV *tmpsv, U32 optype, U32 op_private) {
     const struct op_private_by_op *start = op_private_names;
-    const struct op_private_by_op *const end
-	= op_private_names + C_ARRAY_LENGTH(op_private_names);
+    const struct op_private_by_op *const end = C_ARRAY_END(op_private_names);
 
     /* This is a linear search, but no worse than the code that it replaced.
        It's debugging code - size is more important than speed.  */
@@ -1894,7 +1893,7 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo
 	if (HvARRAY(sv) && usedkeys) {
 	    /* Show distribution of HEs in the ARRAY */
 	    int freq[200];
-#define FREQ_MAX ((int)(sizeof freq / sizeof freq[0] - 1))
+#define FREQ_MAX ((int)(C_ARRAY_LENGTH(freq) - 1))
 	    int i;
 	    int max = 0;
 	    U32 pow2 = 2, keys = usedkeys;
diff --git a/handy.h b/handy.h
index 3f84eff..9332f8d 100644
--- a/handy.h
+++ b/handy.h
@@ -1936,8 +1936,13 @@ void Perl_mem_log_del_sv(const SV *sv, const char *filename, const int linenumbe
 #define StructCopy(s,d,t) Copy(s,d,1,t)
 #endif
 
+/* C_ARRAY_LENGTH is the number of elements in the C array (so you
+ * want your zero-based indices to be less than but not equal to).
+ *
+ * C_ARRAY_END is one past the last: half-open/half-closed range,
+ * not last-inclusive range. */
 #define C_ARRAY_LENGTH(a)	(sizeof(a)/sizeof((a)[0]))
-#define C_ARRAY_END(a)		(a) + (sizeof(a)/sizeof((a)[0]))
+#define C_ARRAY_END(a)		((a) + C_ARRAY_LENGTH(a))
 
 #ifdef NEED_VA_COPY
 # ifdef va_copy
diff --git a/patchlevel.h b/patchlevel.h
index 6567b2f..acd8925 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -144,7 +144,7 @@ static const char * const local_patches[] = {
 
 /* Initial space prevents this variable from being inserted in config.sh  */
 #  define	LOCAL_PATCH_COUNT	\
-	((int)(sizeof(local_patches)/sizeof(local_patches[0])-2))
+	((int)(C_ARRAY_LENGTH(local_patches)-2))
 
 /* the old terms of reference, add them only when explicitly included */
 #define PATCHLEVEL		PERL_VERSION
diff --git a/perl.c b/perl.c
index 27d0d9e..0fb87dc 100644
--- a/perl.c
+++ b/perl.c
@@ -677,7 +677,7 @@ perl_destruct(pTHXx)
 		msg.msg_name = NULL;
 		msg.msg_namelen = 0;
 		msg.msg_iov = vec;
-		msg.msg_iovlen = sizeof(vec)/sizeof(vec[0]);
+		msg.msg_iovlen = C_ARRAY_LENGTH(vec);
 
 		vec[0].iov_base = (void*)&target;
 		vec[0].iov_len = sizeof(target);
diff --git a/regcomp.c b/regcomp.c
index ca2ffb8..0238af9 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -15831,10 +15831,7 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
     }
     else if (k == POSIXD || k == NPOSIXD) {
         U8 index = FLAGS(o) * 2;
-        if (index > (sizeof(anyofs) / sizeof(anyofs[0]))) {
-            Perl_sv_catpvf(aTHX_ sv, "[illegal type=%d])", index);
-        }
-        else {
+        if (index < C_ARRAY_LENGTH(anyofs)) {
             if (*anyofs[index] != '[')  {
                 sv_catpv(sv, "[");
             }
@@ -15843,6 +15840,9 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
                 sv_catpv(sv, "]");
             }
         }
+        else {
+            Perl_sv_catpvf(aTHX_ sv, "[illegal type=%d])", index);
+        }
     }
     else if (k == BRANCHJ && (OP(o) == UNLESSM || OP(o) == IFMATCH))
 	Perl_sv_catpvf(aTHX_ sv, "[%d]", -(o->flags));
diff --git a/sv.c b/sv.c
index 85f91f1..971bf21 100644
--- a/sv.c
+++ b/sv.c
@@ -5557,7 +5557,7 @@ Perl_sv_magic(pTHX_ SV *const sv, SV *const obj, const int how,
 
     PERL_ARGS_ASSERT_SV_MAGIC;
 
-    if (how < 0 || (unsigned)how > C_ARRAY_LENGTH(PL_magic_data)
+    if (how < 0 || (unsigned)how >= C_ARRAY_LENGTH(PL_magic_data)
 	|| ((flags = PL_magic_data[how]),
 	    (vtable_index = flags & PERL_MAGIC_VTABLE_MASK)
 	    > magic_vtable_max))
@@ -12125,8 +12125,7 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *const tbl, const void *const oldsv, void *
 	    new_arena->next = tbl->tbl_arena;
 	    tbl->tbl_arena = new_arena;
 	    tbl->tbl_arena_next = new_arena->array;
-	    tbl->tbl_arena_end = new_arena->array
-		+ sizeof(new_arena->array) / sizeof(new_arena->array[0]);
+	    tbl->tbl_arena_end = C_ARRAY_END(new_arena->array);
 	}
 
 	tblent = tbl->tbl_arena_next++;
diff --git a/universal.c b/universal.c
index bccc8fb..a29696d 100644
--- a/universal.c
+++ b/universal.c
@@ -1059,8 +1059,7 @@ Perl_boot_core_UNIVERSAL(pTHX)
     dVAR;
     static const char file[] = __FILE__;
     const struct xsub_details *xsub = details;
-    const struct xsub_details *end
-	= details + sizeof(details) / sizeof(details[0]);
+    const struct xsub_details *end = C_ARRAY_END(details);
 
     do {
 	newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
diff --git a/util.c b/util.c
index 0a0ee40..b90abe5 100644
--- a/util.c
+++ b/util.c
@@ -4576,8 +4576,8 @@ Perl_init_global_struct(pTHX)
 {
     struct perl_vars *plvarsp = NULL;
 # ifdef PERL_GLOBAL_STRUCT
-    const IV nppaddr = sizeof(Gppaddr)/sizeof(Perl_ppaddr_t);
-    const IV ncheck  = sizeof(Gcheck) /sizeof(Perl_check_t);
+    const IV nppaddr = C_ARRAY_LENGTH(Gppaddr);
+    const IV ncheck  = C_ARRAY_LENGTH(Gcheck);
 #  ifdef PERL_GLOBAL_STRUCT_PRIVATE
     /* PerlMem_malloc() because can't use even safesysmalloc() this early. */
     plvarsp = (struct perl_vars*)PerlMem_malloc(sizeof(struct perl_vars));
-- 
1.9.2

@p5pRT
Copy link
Author

p5pRT commented May 19, 2014

From @tonycoz

On Mon May 12 08​:29​:42 2014, jhi wrote​:

On Monday-201405-05, 20​:41, Tony Cook via RT wrote​:

On Fri May 02 06​:02​:20 2014, jhi wrote​:

Use C_ARRAY_LENGTH and C_ARRAY_END.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found potential off-by-one error in sv.c​:Perl_sv_magic​:
how > C_ARRAY_LENGTH(PL_magic_data)
should probably have been
how >= C_ARRAY_LENGTH(PL_magic_data)
No tests fail, but this seems to be more of an internal sanity check.

Looks good, added to 5.21.1 blockers.

Tony

Updated patch​: found one more spot in regcomp.c, and now using
C_ARRAY_LENGTH in the definition of C_ARRAY_END (duh)

Conflicts due to 53673d9.

Tony

@p5pRT
Copy link
Author

p5pRT commented May 19, 2014

From @jhi

On Monday-201405-19, 3​:00, Tony Cook via RT wrote​:

On Mon May 12 08​:29​:42 2014, jhi wrote​:

On Monday-201405-05, 20​:41, Tony Cook via RT wrote​:

On Fri May 02 06​:02​:20 2014, jhi wrote​:

Use C_ARRAY_LENGTH and C_ARRAY_END.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found potential off-by-one error in sv.c​:Perl_sv_magic​:
how > C_ARRAY_LENGTH(PL_magic_data)
should probably have been
how >= C_ARRAY_LENGTH(PL_magic_data)
No tests fail, but this seems to be more of an internal sanity check.

Looks good, added to 5.21.1 blockers.

Tony

Updated patch​: found one more spot in regcomp.c, and now using
C_ARRAY_LENGTH in the definition of C_ARRAY_END (duh)

Conflicts due to 53673d9.

Updated patch attached.

@p5pRT
Copy link
Author

p5pRT commented May 19, 2014

From @jhi

0001-Use-the-C_ARRAY_LENGTH.patch
From 2c2ee2c3260e8b11176ea98e868583964b1517df Mon Sep 17 00:00:00 2001
From: Jarkko Hietaniemi <jhi@iki.fi>
Date: Mon, 19 May 2014 06:52:24 -0400
Subject: [PATCH] Use the C_ARRAY_LENGTH.

Use the C_ARRAY_LENGTH instead of sizeof(c_array)/sizeof(c_array[0])
or sizeof(c_array)/sizeof(type_of_element_in_c_array), and C_ARRAY_END
for c_array + C_ARRAY_LENGTH(c_array).

While doing this found potential off-by-one error in sv.c:Perl_sv_magic:
how > C_ARRAY_LENGTH(PL_magic_data)
should probably have been
how >= C_ARRAY_LENGTH(PL_magic_data)
No tests fail, but this seems to be more of an internal sanity check.
---
 dump.c       | 5 ++---
 handy.h      | 7 ++++++-
 patchlevel.h | 2 +-
 perl.c       | 2 +-
 sv.c         | 5 ++---
 universal.c  | 3 +--
 util.c       | 4 ++--
 7 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/dump.c b/dump.c
index 354cd57..59be3e0 100644
--- a/dump.c
+++ b/dump.c
@@ -868,8 +868,7 @@ const struct op_private_by_op op_private_names[] = {
 static bool
 S_op_private_to_names(pTHX_ SV *tmpsv, U32 optype, U32 op_private) {
     const struct op_private_by_op *start = op_private_names;
-    const struct op_private_by_op *const end
-	= op_private_names + C_ARRAY_LENGTH(op_private_names);
+    const struct op_private_by_op *const end = C_ARRAY_END(op_private_names);
 
     /* This is a linear search, but no worse than the code that it replaced.
        It's debugging code - size is more important than speed.  */
@@ -1894,7 +1893,7 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo
 	if (HvARRAY(sv) && usedkeys) {
 	    /* Show distribution of HEs in the ARRAY */
 	    int freq[200];
-#define FREQ_MAX ((int)(sizeof freq / sizeof freq[0] - 1))
+#define FREQ_MAX ((int)(C_ARRAY_LENGTH(freq) - 1))
 	    int i;
 	    int max = 0;
 	    U32 pow2 = 2, keys = usedkeys;
diff --git a/handy.h b/handy.h
index 3f84eff..9332f8d 100644
--- a/handy.h
+++ b/handy.h
@@ -1936,8 +1936,13 @@ void Perl_mem_log_del_sv(const SV *sv, const char *filename, const int linenumbe
 #define StructCopy(s,d,t) Copy(s,d,1,t)
 #endif
 
+/* C_ARRAY_LENGTH is the number of elements in the C array (so you
+ * want your zero-based indices to be less than but not equal to).
+ *
+ * C_ARRAY_END is one past the last: half-open/half-closed range,
+ * not last-inclusive range. */
 #define C_ARRAY_LENGTH(a)	(sizeof(a)/sizeof((a)[0]))
-#define C_ARRAY_END(a)		(a) + (sizeof(a)/sizeof((a)[0]))
+#define C_ARRAY_END(a)		((a) + C_ARRAY_LENGTH(a))
 
 #ifdef NEED_VA_COPY
 # ifdef va_copy
diff --git a/patchlevel.h b/patchlevel.h
index 0b50d75..b045f12 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -145,7 +145,7 @@ static const char * const local_patches[] = {
 
 /* Initial space prevents this variable from being inserted in config.sh  */
 #  define	LOCAL_PATCH_COUNT	\
-	((int)(sizeof(local_patches)/sizeof(local_patches[0])-2))
+	((int)(C_ARRAY_LENGTH(local_patches)-2))
 
 /* the old terms of reference, add them only when explicitly included */
 #define PATCHLEVEL		PERL_VERSION
diff --git a/perl.c b/perl.c
index 27d0d9e..0fb87dc 100644
--- a/perl.c
+++ b/perl.c
@@ -677,7 +677,7 @@ perl_destruct(pTHXx)
 		msg.msg_name = NULL;
 		msg.msg_namelen = 0;
 		msg.msg_iov = vec;
-		msg.msg_iovlen = sizeof(vec)/sizeof(vec[0]);
+		msg.msg_iovlen = C_ARRAY_LENGTH(vec);
 
 		vec[0].iov_base = (void*)&target;
 		vec[0].iov_len = sizeof(target);
diff --git a/sv.c b/sv.c
index 1005313..07992a3 100644
--- a/sv.c
+++ b/sv.c
@@ -5581,7 +5581,7 @@ Perl_sv_magic(pTHX_ SV *const sv, SV *const obj, const int how,
 
     PERL_ARGS_ASSERT_SV_MAGIC;
 
-    if (how < 0 || (unsigned)how > C_ARRAY_LENGTH(PL_magic_data)
+    if (how < 0 || (unsigned)how >= C_ARRAY_LENGTH(PL_magic_data)
 	|| ((flags = PL_magic_data[how]),
 	    (vtable_index = flags & PERL_MAGIC_VTABLE_MASK)
 	    > magic_vtable_max))
@@ -12257,8 +12257,7 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *const tbl, const void *const oldsv, void *
 	    new_arena->next = tbl->tbl_arena;
 	    tbl->tbl_arena = new_arena;
 	    tbl->tbl_arena_next = new_arena->array;
-	    tbl->tbl_arena_end = new_arena->array
-		+ sizeof(new_arena->array) / sizeof(new_arena->array[0]);
+	    tbl->tbl_arena_end = C_ARRAY_END(new_arena->array);
 	}
 
 	tblent = tbl->tbl_arena_next++;
diff --git a/universal.c b/universal.c
index bccc8fb..a29696d 100644
--- a/universal.c
+++ b/universal.c
@@ -1059,8 +1059,7 @@ Perl_boot_core_UNIVERSAL(pTHX)
     dVAR;
     static const char file[] = __FILE__;
     const struct xsub_details *xsub = details;
-    const struct xsub_details *end
-	= details + sizeof(details) / sizeof(details[0]);
+    const struct xsub_details *end = C_ARRAY_END(details);
 
     do {
 	newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
diff --git a/util.c b/util.c
index 0a0ee40..b90abe5 100644
--- a/util.c
+++ b/util.c
@@ -4576,8 +4576,8 @@ Perl_init_global_struct(pTHX)
 {
     struct perl_vars *plvarsp = NULL;
 # ifdef PERL_GLOBAL_STRUCT
-    const IV nppaddr = sizeof(Gppaddr)/sizeof(Perl_ppaddr_t);
-    const IV ncheck  = sizeof(Gcheck) /sizeof(Perl_check_t);
+    const IV nppaddr = C_ARRAY_LENGTH(Gppaddr);
+    const IV ncheck  = C_ARRAY_LENGTH(Gcheck);
 #  ifdef PERL_GLOBAL_STRUCT_PRIVATE
     /* PerlMem_malloc() because can't use even safesysmalloc() this early. */
     plvarsp = (struct perl_vars*)PerlMem_malloc(sizeof(struct perl_vars));
-- 
1.8.5.2 (Apple Git-48)

@p5pRT
Copy link
Author

p5pRT commented May 28, 2014

From @tsee

Thanks, most recent version of the patch applied as c3caa5c.

@p5pRT
Copy link
Author

p5pRT commented May 28, 2014

@tsee - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant