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

Broken memcpy() fallback to bcopy() #15200

Closed
p5pRT opened this issue Feb 26, 2016 · 18 comments
Closed

Broken memcpy() fallback to bcopy() #15200

p5pRT opened this issue Feb 26, 2016 · 18 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 26, 2016

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

Searchable as RT127619$

@p5pRT
Copy link
Author

p5pRT commented Feb 26, 2016

From @ilmari

One of the Gentoo perl packagers (Andreas K. Huettel, dilfridge on #p5p)
discovered a problem compiling perl on arm with gcc 4.9.3​:

@​armv7a-hardfloat-linux-gnueabi-gcc -c -DPERL_CORE -fwrapv -fno-strict-aliasing -pipe -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -std=c89 -march=armv7-a -mtune=cortex-a9 -O2 -pipe -mfpu=vfpv3-d16 -mfloat-abi=hard -Wall -Werror=declaration-after-statement -Wextra -Wc++-compat -Wwrite-strings -fPIC -DPERL_IS_MINIPERL -DPERL_EXTERNAL_GLOB perlmini.c
op.c​: In function 'Perl_block_start'​:
op.c​:3898​:5​: error​: invalid use of void expression
  PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings);
  ^
op.c​: In function 'Perl_newSTATEOP'​:
op.c​:6704​:5​: error​: invalid use of void expression
  cop->cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
  ^
op.c​: In function 'Perl_newCONSTSUB_flags'​:
op.c​:8990​:3​: error​: invalid use of void expression
  PL_compiling.cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
  ^

A bit of digging turned up that for some reason Configure wasn't finding
memcpy()​:

$ egrep '^(mem|bcopy)' gentoo.fail.log
bcopy() found.
memchr() found.
memcmp() found.
memcpy() NOT found.
memmove() found.
memset() found.

DUP_WARNINGS is defined in warnings.h in terms of CopyD , which is a
variant of Copy which returns the destination, which is defined in
handy.h in terms of memcpy, which is defined as bcopy() if HAS_MEMCPY is
false.

However, bcopy returns void, not void*, hence the above error. The same
applies to MoveD, while ZeroD correctly handles it (but evaluates dest
twice)​:

#ifdef HAS_MEMSET
#define ZeroD(d,n,t) (MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)))
#else
/* Using bzero(), which returns void. */
#define ZeroD(d,n,t) (MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)),d)
#endif

For systems that don't have bcopy or bzero either, there are alleged
"drop-in replacement[s]" in util.c, but trying to use these spews
warnings all over the place, because they use char* and I32 insted of
void* and size_t like they should.

Either we should make sure these fallbacks actually work, or we should
remove them and stop pretending we support systems without the mem*
functions.

--
"The surreality of the universe tends towards a maximum" -- Skud's Law
"Never formulate a law or axiom that you're not prepared to live with
the consequences of." -- Skud's Meta-Law

@p5pRT
Copy link
Author

p5pRT commented Feb 26, 2016

From @mauke

On Fri Feb 26 08​:05​:38 2016, ilmari wrote​:

op.c​: In function 'Perl_block_start'​:
op.c​:3898​:5​: error​: invalid use of void expression
PL_compiling.cop_warnings =
DUP_WARNINGS(PL_compiling.cop_warnings);
^
op.c​: In function 'Perl_newSTATEOP'​:
op.c​:6704​:5​: error​: invalid use of void expression
cop->cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
^
op.c​: In function 'Perl_newCONSTSUB_flags'​:
op.c​:8990​:3​: error​: invalid use of void expression
PL_compiling.cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
^

DUP_WARNINGS is defined in warnings.h in terms of CopyD , which is a
variant of Copy which returns the destination, which is defined in
handy.h in terms of memcpy, which is defined as bcopy() if HAS_MEMCPY
is
false.

However, bcopy returns void, not void*, hence the above error.

I don't know why it doesn't find memcpy, but here's a possible patch to successfully build without memcpy.

The idea is to always use my_bcopy (which has the right return value), but optionally implement it using bcopy.

@p5pRT
Copy link
Author

p5pRT commented Feb 26, 2016

From @mauke

0001-make-building-without-memcpy-work-RT-127619.patch
From 0631e11975ff59e74f1a7b24c8605a158574a953 Mon Sep 17 00:00:00 2001
From: Lukas Mai <l.mai@web.de>
Date: Fri, 26 Feb 2016 17:12:40 +0100
Subject: [PATCH] make building without memcpy work (RT #127619)

---
 embed.fnc |  2 +-
 embed.h   |  6 +++---
 perl.h    | 16 ++++------------
 proto.h   | 10 +++++-----
 util.c    |  7 ++++++-
 5 files changed, 19 insertions(+), 22 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index c35a815..fc4e4ca 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -931,7 +931,7 @@ s	|void	|move_proto_attr|NN OP **proto|NN OP **attrs|NN const GV *name
 p	|int	|mode_from_discipline|NULLOK const char* s|STRLEN len
 Ap	|const char*	|moreswitches	|NN const char* s
 Ap	|NV	|my_atof	|NN const char *s
-#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
+#if !defined(HAS_MEMCPY) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY))
 Anp	|char*	|my_bcopy	|NN const char* from|NN char* to|I32 len
 #endif
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
diff --git a/embed.h b/embed.h
index 75275c4..0c8ed07 100644
--- a/embed.h
+++ b/embed.h
@@ -764,6 +764,9 @@
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
 #define my_memcmp		Perl_my_memcmp
 #endif
+#if !defined(HAS_MEMCPY) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY))
+#define my_bcopy		Perl_my_bcopy
+#endif
 #if !defined(HAS_MEMSET)
 #define my_memset		Perl_my_memset
 #endif
@@ -798,9 +801,6 @@
 #define cx_topblock(a)		S_cx_topblock(aTHX_ a)
 #define is_safe_syscall(a,b,c,d)	S_is_safe_syscall(aTHX_ a,b,c,d)
 #endif
-#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-#define my_bcopy		Perl_my_bcopy
-#endif
 #if defined(DEBUGGING)
 #define pad_setsv(a,b)		Perl_pad_setsv(aTHX_ a,b)
 #define pad_sv(a)		Perl_pad_sv(aTHX_ a)
diff --git a/perl.h b/perl.h
index c60aeef..b387257 100644
--- a/perl.h
+++ b/perl.h
@@ -1007,11 +1007,7 @@ EXTERN_C int usleep(unsigned int);
 #  endif
 #else
 #   ifndef memcpy
-#	ifdef HAS_BCOPY
-#	    define memcpy(d,s,l) bcopy(s,d,l)
-#	else
-#	    define memcpy(d,s,l) my_bcopy(s,d,l)
-#	endif
+#	define memcpy(d,s,l) my_bcopy(s,d,l)
 #   endif
 #endif /* HAS_MEMCPY */
 
@@ -1027,14 +1023,10 @@ EXTERN_C int usleep(unsigned int);
 #endif /* HAS_MEMSET */
 
 #if !defined(HAS_MEMMOVE) && !defined(memmove)
-#   if defined(HAS_BCOPY) && defined(HAS_SAFE_BCOPY)
-#	define memmove(d,s,l) bcopy(s,d,l)
+#   if defined(HAS_MEMCPY) && defined(HAS_SAFE_MEMCPY)
+#	define memmove(d,s,l) memcpy(d,s,l)
 #   else
-#	if defined(HAS_MEMCPY) && defined(HAS_SAFE_MEMCPY)
-#	    define memmove(d,s,l) memcpy(d,s,l)
-#	else
-#	    define memmove(d,s,l) my_bcopy(s,d,l)
-#	endif
+#	define memmove(d,s,l) my_bcopy(s,d,l)
 #   endif
 #endif
 
diff --git a/proto.h b/proto.h
index 9f970a3..91749cf 100644
--- a/proto.h
+++ b/proto.h
@@ -3599,6 +3599,11 @@ PERL_CALLCONV I32	Perl_my_memcmp(const char* s1, const char* s2, I32 len)
 	assert(s1); assert(s2)
 
 #endif
+#if !defined(HAS_MEMCPY) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY))
+PERL_CALLCONV char*	Perl_my_bcopy(const char* from, char* to, I32 len);
+#define PERL_ARGS_ASSERT_MY_BCOPY	\
+	assert(from); assert(to)
+#endif
 #if !defined(HAS_MEMSET)
 PERL_CALLCONV void*	Perl_my_memset(char* loc, I32 ch, I32 len);
 #define PERL_ARGS_ASSERT_MY_MEMSET	\
@@ -3797,11 +3802,6 @@ PERL_CALLCONV bool	Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
 #define PERL_ARGS_ASSERT_DO_EXEC3	\
 	assert(incmd)
 #endif
-#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-PERL_CALLCONV char*	Perl_my_bcopy(const char* from, char* to, I32 len);
-#define PERL_ARGS_ASSERT_MY_BCOPY	\
-	assert(from); assert(to)
-#endif
 #if defined(DEBUGGING)
 PERL_CALLCONV int	Perl_get_debug_opts(pTHX_ const char **s, bool givehelp)
 			__attribute__warn_unused_result__;
diff --git a/util.c b/util.c
index e87246b..f3718f3 100644
--- a/util.c
+++ b/util.c
@@ -2264,7 +2264,7 @@ Perl_unlnk(pTHX_ const char *f)	/* unlink all versions of a file */
 #endif
 
 /* this is a drop-in replacement for bcopy() */
-#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
+#if !defined(HAS_MEMCPY) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY))
 char *
 Perl_my_bcopy(const char *from, char *to, I32 len)
 {
@@ -2274,6 +2274,9 @@ Perl_my_bcopy(const char *from, char *to, I32 len)
 
     assert(len >= 0);
 
+#if defined(HAS_BCOPY) && defined(HAS_SAFE_BCOPY)
+    bcopy(from, to, len);
+#else
     if (from - to >= 0) {
 	while (len--)
 	    *to++ = *from++;
@@ -2284,6 +2287,8 @@ Perl_my_bcopy(const char *from, char *to, I32 len)
 	while (len--)
 	    *(--to) = *(--from);
     }
+#endif
+
     return retval;
 }
 #endif
-- 
2.7.1

@p5pRT
Copy link
Author

p5pRT commented Feb 26, 2016

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

@p5pRT
Copy link
Author

p5pRT commented Feb 26, 2016

From dilfridge@gentoo.org

On Fri Feb 26 08​:05​:38 2016, ilmari wrote​:

One of the Gentoo perl packagers (Andreas K. Huettel, dilfridge on
#p5p)
discovered a problem compiling perl on arm with gcc 4.9.3​:

Just for reference this is the original bug report​:
https://bugs.gentoo.org/show_bug.cgi?id=575342

@p5pRT
Copy link
Author

p5pRT commented Feb 26, 2016

From @bulk88

On Fri Feb 26 08​:05​:38 2016, ilmari wrote​:

A bit of digging turned up that for some reason Configure wasn't
finding
memcpy()​:

Perl core in some places is using memcpy directly,

http​://perl5.git.perl.org/perl.git/blob/HEAD​:/doio.c#l1610
http​://perl5.git.perl.org/perl.git/blob/HEAD​:/gv.c#l122
http​://perl5.git.perl.org/perl.git/blob/HEAD​:/pp_ctl.c#l3917

and so forth. We aren't eating out own dog food. Perl clearly can't be compiled on an ancient unix OS without memcpy and only bcopy.

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Feb 26, 2016

From @mauke

Am 26.02.2016 um 17​:55 schrieb bulk88 via RT​:

On Fri Feb 26 08​:05​:38 2016, ilmari wrote​:

A bit of digging turned up that for some reason Configure wasn't
finding
memcpy()​:

Perl core in some places is using memcpy directly,

http​://perl5.git.perl.org/perl.git/blob/HEAD​:/doio.c#l1610
http​://perl5.git.perl.org/perl.git/blob/HEAD​:/gv.c#l122
http​://perl5.git.perl.org/perl.git/blob/HEAD​:/pp_ctl.c#l3917

and so forth. We aren't eating out own dog food. Perl clearly can't be compiled on an ancient unix OS without memcpy and only bcopy.

No, see http​://perl5.git.perl.org/perl.git/blob/a975eebad​:/perl.h#l1002

We redefine memcpy() if it doesn't exist.

--
Lukas Mai <plokinom@​gmail.com>

@p5pRT
Copy link
Author

p5pRT commented Feb 28, 2016

From @tonycoz

On Fri Feb 26 08​:16​:16 2016, mauke- wrote​:

I don't know why it doesn't find memcpy, but here's a possible patch
to successfully build without memcpy.

The idea is to always use my_bcopy (which has the right return value),
but optionally implement it using bcopy.

I expect we need to update the prototype of my_bcopy(), according to man bcopy​:

  void bcopy(const void *src, void *dest, size_t n);

while we have​:

  char* Perl_my_bcopy(const char* from, char* to, I32 len);

this causes warnings like​:

  regcomp.c​: In function ‘Perl_reg_temp_copy’​:
  regcomp.c​:18980​:29​: warning​: passing argument 1 of ‘Perl_my_bcopy’ from incompatible pointer type
  memcpy(&(ret->xpv_cur), &(r->xpv_cur),
  ^
  perl.h​:1010​:33​: note​: in definition of macro ‘memcpy’
  # define memcpy(d,s,l) my_bcopy(s,d,l)
  ^
Tony

@p5pRT
Copy link
Author

p5pRT commented Feb 29, 2016

From @mauke

On Sun Feb 28 15​:57​:01 2016, tonyc wrote​:

On Fri Feb 26 08​:16​:16 2016, mauke- wrote​:

I don't know why it doesn't find memcpy, but here's a possible patch
to successfully build without memcpy.

The idea is to always use my_bcopy (which has the right return
value),
but optionally implement it using bcopy.

I expect we need to update the prototype of my_bcopy(), according to
man bcopy​:

void bcopy(const void *src, void *dest, size_t n);

while we have​:

char* Perl_my_bcopy(const char* from, char* to, I32 len);

this causes warnings like​:

regcomp.c​: In function ‘Perl_reg_temp_copy’​:
regcomp.c​:18980​:29​: warning​: passing argument 1 of ‘Perl_my_bcopy’
from incompatible pointer type
memcpy(&(ret->xpv_cur), &(r->xpv_cur),
^
perl.h​:1010​:33​: note​: in definition of macro ‘memcpy’
# define memcpy(d,s,l) my_bcopy(s,d,l)
^
Tony

Here's an untested patch for that.

@p5pRT
Copy link
Author

p5pRT commented Feb 29, 2016

From @mauke

0001-util.c-make-my_mem-my_b-prototypes-more-like-the-ori.patch
From 1dfe3e0633dd9c6142eb5bf01287ef71fef674da Mon Sep 17 00:00:00 2001
From: Lukas Mai <l.mai@web.de>
Date: Mon, 29 Feb 2016 08:45:12 +0100
Subject: [PATCH] util.c: make my_mem*/my_b* prototypes more like the originals

---
 embed.fnc |  8 ++++----
 proto.h   | 16 ++++++++--------
 util.c    | 44 +++++++++++++++++++-------------------------
 3 files changed, 31 insertions(+), 37 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index a08ebdc..a523972 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -932,10 +932,10 @@ p	|int	|mode_from_discipline|NULLOK const char* s|STRLEN len
 Ap	|const char*	|moreswitches	|NN const char* s
 Ap	|NV	|my_atof	|NN const char *s
 #if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-Anp	|char*	|my_bcopy	|NN const char* from|NN char* to|I32 len
+Anp	|void*	|my_bcopy	|NN const void* vfrom|NN void* to|size_t len
 #endif
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
-Anp	|char*	|my_bzero	|NN char* loc|I32 len
+Anp	|void*	|my_bzero	|NN void* vloc|size_t len
 #endif
 Apr	|void	|my_exit	|U32 status
 Apr	|void	|my_failure_exit
@@ -946,10 +946,10 @@ Anp	|void	|atfork_unlock
 Apmb	|I32	|my_lstat
 pX	|I32	|my_lstat_flags	|NULLOK const U32 flags
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
-AnpP	|I32	|my_memcmp	|NN const char* s1|NN const char* s2|I32 len
+AnpP	|int	|my_memcmp	|NN const void* vs1|NN const void* vs2|size_t len
 #endif
 #if !defined(HAS_MEMSET)
-Anp	|void*	|my_memset	|NN char* loc|I32 ch|I32 len
+Anp	|void*	|my_memset	|NN void* vloc|int ch|size_t len
 #endif
 #if !defined(PERL_IMPLICIT_SYS)
 Ap	|I32	|my_pclose	|NULLOK PerlIO* ptr
diff --git a/proto.h b/proto.h
index 0762b5c..fe78454 100644
--- a/proto.h
+++ b/proto.h
@@ -3583,9 +3583,9 @@ PERL_CALLCONV_NO_RET int	Perl_magic_regdatum_set(pTHX_ SV* sv, MAGIC* mg)
 
 #endif
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
-PERL_CALLCONV char*	Perl_my_bzero(char* loc, I32 len);
+PERL_CALLCONV void*	Perl_my_bzero(void* vloc, size_t len);
 #define PERL_ARGS_ASSERT_MY_BZERO	\
-	assert(loc)
+	assert(vloc)
 #endif
 #if !defined(HAS_GETENV_LEN)
 PERL_CALLCONV char*	Perl_getenv_len(pTHX_ const char *env_elem, unsigned long *len);
@@ -3593,16 +3593,16 @@ PERL_CALLCONV char*	Perl_getenv_len(pTHX_ const char *env_elem, unsigned long *l
 	assert(env_elem); assert(len)
 #endif
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
-PERL_CALLCONV I32	Perl_my_memcmp(const char* s1, const char* s2, I32 len)
+PERL_CALLCONV int	Perl_my_memcmp(const void* vs1, const void* vs2, size_t len)
 			__attribute__pure__;
 #define PERL_ARGS_ASSERT_MY_MEMCMP	\
-	assert(s1); assert(s2)
+	assert(vs1); assert(vs2)
 
 #endif
 #if !defined(HAS_MEMSET)
-PERL_CALLCONV void*	Perl_my_memset(char* loc, I32 ch, I32 len);
+PERL_CALLCONV void*	Perl_my_memset(void* vloc, int ch, size_t len);
 #define PERL_ARGS_ASSERT_MY_MEMSET	\
-	assert(loc)
+	assert(vloc)
 #endif
 #if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
 #  if defined(PERL_IN_PP_SYS_C)
@@ -3798,9 +3798,9 @@ PERL_CALLCONV bool	Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
 	assert(incmd)
 #endif
 #if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-PERL_CALLCONV char*	Perl_my_bcopy(const char* from, char* to, I32 len);
+PERL_CALLCONV void*	Perl_my_bcopy(const void* vfrom, void* to, size_t len);
 #define PERL_ARGS_ASSERT_MY_BCOPY	\
-	assert(from); assert(to)
+	assert(vfrom); assert(to)
 #endif
 #if defined(DEBUGGING)
 PERL_CALLCONV int	Perl_get_debug_opts(pTHX_ const char **s, bool givehelp)
diff --git a/util.c b/util.c
index e87246b..4c9516b 100644
--- a/util.c
+++ b/util.c
@@ -2263,17 +2263,17 @@ Perl_unlnk(pTHX_ const char *f)	/* unlink all versions of a file */
 }
 #endif
 
-/* this is a drop-in replacement for bcopy() */
+/* this is a drop-in replacement for bcopy(), except for the return
+ * value, which we need to be able to emulate memcpy()  */
 #if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-char *
-Perl_my_bcopy(const char *from, char *to, I32 len)
+void *
+Perl_my_bcopy(const void *vfrom, void *vto, size_t len)
 {
-    char * const retval = to;
+    const unsigned char *from = (const unsigned char *)vfrom;
+    unsigned char *to = (unsigned char *)vto;
 
     PERL_ARGS_ASSERT_MY_BCOPY;
 
-    assert(len >= 0);
-
     if (from - to >= 0) {
 	while (len--)
 	    *to++ = *from++;
@@ -2284,57 +2284,51 @@ Perl_my_bcopy(const char *from, char *to, I32 len)
 	while (len--)
 	    *(--to) = *(--from);
     }
-    return retval;
+    return vto;
 }
 #endif
 
 /* this is a drop-in replacement for memset() */
 #ifndef HAS_MEMSET
 void *
-Perl_my_memset(char *loc, I32 ch, I32 len)
+Perl_my_memset(void *vloc, int ch, size_t len)
 {
-    char * const retval = loc;
+    unsigned char *loc = (unsigned char *)vloc;
 
     PERL_ARGS_ASSERT_MY_MEMSET;
 
-    assert(len >= 0);
-
     while (len--)
 	*loc++ = ch;
-    return retval;
+    return vloc;
 }
 #endif
 
 /* this is a drop-in replacement for bzero() */
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
-char *
-Perl_my_bzero(char *loc, I32 len)
+void *
+Perl_my_bzero(void *vloc, size_t len)
 {
-    char * const retval = loc;
+    unsigned char *loc = (unsigned char *)vloc;
 
     PERL_ARGS_ASSERT_MY_BZERO;
 
-    assert(len >= 0);
-
     while (len--)
 	*loc++ = 0;
-    return retval;
+    return vloc;
 }
 #endif
 
 /* this is a drop-in replacement for memcmp() */
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
-I32
-Perl_my_memcmp(const char *s1, const char *s2, I32 len)
+int
+Perl_my_memcmp(const void *vs1, const void *vs2, size_t len)
 {
-    const U8 *a = (const U8 *)s1;
-    const U8 *b = (const U8 *)s2;
-    I32 tmp;
+    const U8 *a = (const U8 *)vs1;
+    const U8 *b = (const U8 *)vs2;
+    int tmp;
 
     PERL_ARGS_ASSERT_MY_MEMCMP;
 
-    assert(len >= 0);
-
     while (len--) {
         if ((tmp = *a++ - *b++))
 	    return tmp;
-- 
2.7.1

@p5pRT
Copy link
Author

p5pRT commented Mar 2, 2016

From @tonycoz

On Sun Feb 28 23​:46​:21 2016, mauke- wrote​:

Here's an untested patch for that.

The two patches conflict with each other.

Tony

@p5pRT
Copy link
Author

p5pRT commented Mar 3, 2016

From @mauke

On Wed Mar 02 15​:34​:27 2016, tonyc wrote​:

On Sun Feb 28 23​:46​:21 2016, mauke- wrote​:

Here's an untested patch for that.

The two patches conflict with each other.

I've attached two patches​:

1. A revised version of the type change patch to mimic the original functions more closely.
2. The my_bcopy patch to make building without memcpy work, rebased on top of #1.

@p5pRT
Copy link
Author

p5pRT commented Mar 3, 2016

From @mauke

0001-util.c-make-my_mem-my_b-prototypes-more-like-the-ori.patch
From 79b78e8ceb0e3f76177ddd0e563a11622e9f9b88 Mon Sep 17 00:00:00 2001
From: Lukas Mai <l.mai@web.de>
Date: Mon, 29 Feb 2016 08:45:12 +0100
Subject: [PATCH 1/2] util.c: make my_mem*/my_b* prototypes more like the
 originals

---
 embed.fnc |  8 ++++----
 proto.h   | 16 ++++++++--------
 util.c    | 44 +++++++++++++++++++-------------------------
 3 files changed, 31 insertions(+), 37 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index 636b61a..a5fa279 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -932,10 +932,10 @@ p	|int	|mode_from_discipline|NULLOK const char* s|STRLEN len
 Ap	|const char*	|moreswitches	|NN const char* s
 Ap	|NV	|my_atof	|NN const char *s
 #if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-Anp	|char*	|my_bcopy	|NN const char* from|NN char* to|I32 len
+Anp	|void*	|my_bcopy	|NN const void* vfrom|NN void* vto|size_t len
 #endif
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
-Anp	|char*	|my_bzero	|NN char* loc|I32 len
+Anp	|void*	|my_bzero	|NN void* vloc|size_t len
 #endif
 Apr	|void	|my_exit	|U32 status
 Apr	|void	|my_failure_exit
@@ -946,10 +946,10 @@ Anp	|void	|atfork_unlock
 Apmb	|I32	|my_lstat
 pX	|I32	|my_lstat_flags	|NULLOK const U32 flags
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
-AnpP	|I32	|my_memcmp	|NN const char* s1|NN const char* s2|I32 len
+AnpP	|int	|my_memcmp	|NN const void* vs1|NN const void* vs2|size_t len
 #endif
 #if !defined(HAS_MEMSET)
-Anp	|void*	|my_memset	|NN char* loc|I32 ch|I32 len
+Anp	|void*	|my_memset	|NN void* vloc|int ch|size_t len
 #endif
 #if !defined(PERL_IMPLICIT_SYS)
 Ap	|I32	|my_pclose	|NULLOK PerlIO* ptr
diff --git a/proto.h b/proto.h
index cfd01d8..98ffb3d 100644
--- a/proto.h
+++ b/proto.h
@@ -3583,9 +3583,9 @@ PERL_CALLCONV_NO_RET int	Perl_magic_regdatum_set(pTHX_ SV* sv, MAGIC* mg)
 
 #endif
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
-PERL_CALLCONV char*	Perl_my_bzero(char* loc, I32 len);
+PERL_CALLCONV void*	Perl_my_bzero(void* vloc, size_t len);
 #define PERL_ARGS_ASSERT_MY_BZERO	\
-	assert(loc)
+	assert(vloc)
 #endif
 #if !defined(HAS_GETENV_LEN)
 PERL_CALLCONV char*	Perl_getenv_len(pTHX_ const char *env_elem, unsigned long *len);
@@ -3593,16 +3593,16 @@ PERL_CALLCONV char*	Perl_getenv_len(pTHX_ const char *env_elem, unsigned long *l
 	assert(env_elem); assert(len)
 #endif
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
-PERL_CALLCONV I32	Perl_my_memcmp(const char* s1, const char* s2, I32 len)
+PERL_CALLCONV int	Perl_my_memcmp(const void* vs1, const void* vs2, size_t len)
 			__attribute__pure__;
 #define PERL_ARGS_ASSERT_MY_MEMCMP	\
-	assert(s1); assert(s2)
+	assert(vs1); assert(vs2)
 
 #endif
 #if !defined(HAS_MEMSET)
-PERL_CALLCONV void*	Perl_my_memset(char* loc, I32 ch, I32 len);
+PERL_CALLCONV void*	Perl_my_memset(void* vloc, int ch, size_t len);
 #define PERL_ARGS_ASSERT_MY_MEMSET	\
-	assert(loc)
+	assert(vloc)
 #endif
 #if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
 #  if defined(PERL_IN_PP_SYS_C)
@@ -3801,9 +3801,9 @@ PERL_CALLCONV bool	Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
 	assert(incmd)
 #endif
 #if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-PERL_CALLCONV char*	Perl_my_bcopy(const char* from, char* to, I32 len);
+PERL_CALLCONV void*	Perl_my_bcopy(const void* vfrom, void* vto, size_t len);
 #define PERL_ARGS_ASSERT_MY_BCOPY	\
-	assert(from); assert(to)
+	assert(vfrom); assert(vto)
 #endif
 #if defined(DEBUGGING)
 PERL_CALLCONV int	Perl_get_debug_opts(pTHX_ const char **s, bool givehelp)
diff --git a/util.c b/util.c
index e87246b..4c9516b 100644
--- a/util.c
+++ b/util.c
@@ -2263,17 +2263,17 @@ Perl_unlnk(pTHX_ const char *f)	/* unlink all versions of a file */
 }
 #endif
 
-/* this is a drop-in replacement for bcopy() */
+/* this is a drop-in replacement for bcopy(), except for the return
+ * value, which we need to be able to emulate memcpy()  */
 #if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-char *
-Perl_my_bcopy(const char *from, char *to, I32 len)
+void *
+Perl_my_bcopy(const void *vfrom, void *vto, size_t len)
 {
-    char * const retval = to;
+    const unsigned char *from = (const unsigned char *)vfrom;
+    unsigned char *to = (unsigned char *)vto;
 
     PERL_ARGS_ASSERT_MY_BCOPY;
 
-    assert(len >= 0);
-
     if (from - to >= 0) {
 	while (len--)
 	    *to++ = *from++;
@@ -2284,57 +2284,51 @@ Perl_my_bcopy(const char *from, char *to, I32 len)
 	while (len--)
 	    *(--to) = *(--from);
     }
-    return retval;
+    return vto;
 }
 #endif
 
 /* this is a drop-in replacement for memset() */
 #ifndef HAS_MEMSET
 void *
-Perl_my_memset(char *loc, I32 ch, I32 len)
+Perl_my_memset(void *vloc, int ch, size_t len)
 {
-    char * const retval = loc;
+    unsigned char *loc = (unsigned char *)vloc;
 
     PERL_ARGS_ASSERT_MY_MEMSET;
 
-    assert(len >= 0);
-
     while (len--)
 	*loc++ = ch;
-    return retval;
+    return vloc;
 }
 #endif
 
 /* this is a drop-in replacement for bzero() */
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
-char *
-Perl_my_bzero(char *loc, I32 len)
+void *
+Perl_my_bzero(void *vloc, size_t len)
 {
-    char * const retval = loc;
+    unsigned char *loc = (unsigned char *)vloc;
 
     PERL_ARGS_ASSERT_MY_BZERO;
 
-    assert(len >= 0);
-
     while (len--)
 	*loc++ = 0;
-    return retval;
+    return vloc;
 }
 #endif
 
 /* this is a drop-in replacement for memcmp() */
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
-I32
-Perl_my_memcmp(const char *s1, const char *s2, I32 len)
+int
+Perl_my_memcmp(const void *vs1, const void *vs2, size_t len)
 {
-    const U8 *a = (const U8 *)s1;
-    const U8 *b = (const U8 *)s2;
-    I32 tmp;
+    const U8 *a = (const U8 *)vs1;
+    const U8 *b = (const U8 *)vs2;
+    int tmp;
 
     PERL_ARGS_ASSERT_MY_MEMCMP;
 
-    assert(len >= 0);
-
     while (len--) {
         if ((tmp = *a++ - *b++))
 	    return tmp;
-- 
2.7.1

@p5pRT
Copy link
Author

p5pRT commented Mar 3, 2016

From @mauke

0002-make-building-without-memcpy-work-RT-127619.patch
From 82f4eb339567fea80d023681e2b8f9fde4fd0462 Mon Sep 17 00:00:00 2001
From: Lukas Mai <l.mai@web.de>
Date: Fri, 4 Mar 2016 00:21:27 +0100
Subject: [PATCH 2/2] make building without memcpy work (RT #127619)

---
 embed.fnc |  2 +-
 embed.h   |  6 +++---
 perl.h    | 16 ++++------------
 proto.h   | 10 +++++-----
 util.c    |  7 ++++++-
 5 files changed, 19 insertions(+), 22 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index a5fa279..f918622 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -931,7 +931,7 @@ s	|void	|move_proto_attr|NN OP **proto|NN OP **attrs|NN const GV *name
 p	|int	|mode_from_discipline|NULLOK const char* s|STRLEN len
 Ap	|const char*	|moreswitches	|NN const char* s
 Ap	|NV	|my_atof	|NN const char *s
-#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
+#if !defined(HAS_MEMCPY) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY))
 Anp	|void*	|my_bcopy	|NN const void* vfrom|NN void* vto|size_t len
 #endif
 #if !defined(HAS_BZERO) && !defined(HAS_MEMSET)
diff --git a/embed.h b/embed.h
index 2c91161..93cdfd9 100644
--- a/embed.h
+++ b/embed.h
@@ -764,6 +764,9 @@
 #if !defined(HAS_MEMCMP) || !defined(HAS_SANE_MEMCMP)
 #define my_memcmp		Perl_my_memcmp
 #endif
+#if !defined(HAS_MEMCPY) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY))
+#define my_bcopy		Perl_my_bcopy
+#endif
 #if !defined(HAS_MEMSET)
 #define my_memset		Perl_my_memset
 #endif
@@ -798,9 +801,6 @@
 #define cx_topblock(a)		S_cx_topblock(aTHX_ a)
 #define is_safe_syscall(a,b,c,d)	S_is_safe_syscall(aTHX_ a,b,c,d)
 #endif
-#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-#define my_bcopy		Perl_my_bcopy
-#endif
 #if defined(DEBUGGING)
 #define pad_setsv(a,b)		Perl_pad_setsv(aTHX_ a,b)
 #define pad_sv(a)		Perl_pad_sv(aTHX_ a)
diff --git a/perl.h b/perl.h
index c60aeef..b387257 100644
--- a/perl.h
+++ b/perl.h
@@ -1007,11 +1007,7 @@ EXTERN_C int usleep(unsigned int);
 #  endif
 #else
 #   ifndef memcpy
-#	ifdef HAS_BCOPY
-#	    define memcpy(d,s,l) bcopy(s,d,l)
-#	else
-#	    define memcpy(d,s,l) my_bcopy(s,d,l)
-#	endif
+#	define memcpy(d,s,l) my_bcopy(s,d,l)
 #   endif
 #endif /* HAS_MEMCPY */
 
@@ -1027,14 +1023,10 @@ EXTERN_C int usleep(unsigned int);
 #endif /* HAS_MEMSET */
 
 #if !defined(HAS_MEMMOVE) && !defined(memmove)
-#   if defined(HAS_BCOPY) && defined(HAS_SAFE_BCOPY)
-#	define memmove(d,s,l) bcopy(s,d,l)
+#   if defined(HAS_MEMCPY) && defined(HAS_SAFE_MEMCPY)
+#	define memmove(d,s,l) memcpy(d,s,l)
 #   else
-#	if defined(HAS_MEMCPY) && defined(HAS_SAFE_MEMCPY)
-#	    define memmove(d,s,l) memcpy(d,s,l)
-#	else
-#	    define memmove(d,s,l) my_bcopy(s,d,l)
-#	endif
+#	define memmove(d,s,l) my_bcopy(s,d,l)
 #   endif
 #endif
 
diff --git a/proto.h b/proto.h
index 98ffb3d..2e7cb43 100644
--- a/proto.h
+++ b/proto.h
@@ -3599,6 +3599,11 @@ PERL_CALLCONV int	Perl_my_memcmp(const void* vs1, const void* vs2, size_t len)
 	assert(vs1); assert(vs2)
 
 #endif
+#if !defined(HAS_MEMCPY) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY))
+PERL_CALLCONV void*	Perl_my_bcopy(const void* vfrom, void* vto, size_t len);
+#define PERL_ARGS_ASSERT_MY_BCOPY	\
+	assert(vfrom); assert(vto)
+#endif
 #if !defined(HAS_MEMSET)
 PERL_CALLCONV void*	Perl_my_memset(void* vloc, int ch, size_t len);
 #define PERL_ARGS_ASSERT_MY_MEMSET	\
@@ -3800,11 +3805,6 @@ PERL_CALLCONV bool	Perl_do_exec3(pTHX_ const char *incmd, int fd, int do_report)
 #define PERL_ARGS_ASSERT_DO_EXEC3	\
 	assert(incmd)
 #endif
-#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
-PERL_CALLCONV void*	Perl_my_bcopy(const void* vfrom, void* vto, size_t len);
-#define PERL_ARGS_ASSERT_MY_BCOPY	\
-	assert(vfrom); assert(vto)
-#endif
 #if defined(DEBUGGING)
 PERL_CALLCONV int	Perl_get_debug_opts(pTHX_ const char **s, bool givehelp)
 			__attribute__warn_unused_result__;
diff --git a/util.c b/util.c
index 4c9516b..386707b 100644
--- a/util.c
+++ b/util.c
@@ -2265,10 +2265,13 @@ Perl_unlnk(pTHX_ const char *f)	/* unlink all versions of a file */
 
 /* this is a drop-in replacement for bcopy(), except for the return
  * value, which we need to be able to emulate memcpy()  */
-#if (!defined(HAS_MEMCPY) && !defined(HAS_BCOPY)) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY) && !defined(HAS_SAFE_BCOPY))
+#if !defined(HAS_MEMCPY) || (!defined(HAS_MEMMOVE) && !defined(HAS_SAFE_MEMCPY))
 void *
 Perl_my_bcopy(const void *vfrom, void *vto, size_t len)
 {
+#if defined(HAS_BCOPY) && defined(HAS_SAFE_BCOPY)
+    bcopy(vfrom, vto, len);
+#else
     const unsigned char *from = (const unsigned char *)vfrom;
     unsigned char *to = (unsigned char *)vto;
 
@@ -2284,6 +2287,8 @@ Perl_my_bcopy(const void *vfrom, void *vto, size_t len)
 	while (len--)
 	    *(--to) = *(--from);
     }
+#endif
+
     return vto;
 }
 #endif
-- 
2.7.1

@p5pRT
Copy link
Author

p5pRT commented Mar 7, 2016

From @tonycoz

On Thu Mar 03 15​:54​:27 2016, mauke- wrote​:

On Wed Mar 02 15​:34​:27 2016, tonyc wrote​:

On Sun Feb 28 23​:46​:21 2016, mauke- wrote​:

Here's an untested patch for that.

The two patches conflict with each other.

I've attached two patches​:

1. A revised version of the type change patch to mimic the original
functions more closely.
2. The my_bcopy patch to make building without memcpy work, rebased on
top of #1.

Thanks, applied as 99fff99 and af4291a.

Tony

@p5pRT
Copy link
Author

p5pRT commented Mar 7, 2016

@tonycoz - Status changed from 'open' to 'pending release'

@p5pRT
Copy link
Author

p5pRT commented May 13, 2016

From @khwilliamson

Thank you for submitting this report. You have helped make Perl better.
 
With the release of Perl 5.24.0 on May 9, 2016, this and 149 other issues have been resolved.

Perl 5.24.0 may be downloaded via https://metacpan.org/release/RJBS/perl-5.24.0

@p5pRT p5pRT closed this as completed May 13, 2016
@p5pRT
Copy link
Author

p5pRT commented May 13, 2016

@khwilliamson - Status changed from 'pending release' to 'resolved'

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

No branches or pull requests

1 participant