This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Use the C_ARRAY_LENGTH.
authorJarkko Hietaniemi <jhi@iki.fi>
Mon, 19 May 2014 10:52:24 +0000 (06:52 -0400)
committerSteffen Mueller <smueller@cpan.org>
Wed, 28 May 2014 13:20:52 +0000 (15:20 +0200)
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
handy.h
patchlevel.h
perl.c
sv.c
universal.c
util.c

diff --git a/dump.c b/dump.c
index 354cd57..59be3e0 100644 (file)
--- 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 (file)
--- 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
index 3235cc3..3101f08 100644 (file)
@@ -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 1b9b429..86fb8d9 100644 (file)
--- 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 1dbd3fe..060a4cc 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -5574,7 +5574,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))
@@ -12248,8 +12248,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++;
index bccc8fb..a29696d 100644 (file)
@@ -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 (file)
--- 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));