34484a
From 7a962424149cc60f3a187d0213a12689dd5e806b Mon Sep 17 00:00:00 2001
34484a
From: Tony Cook <tony@develop-help.com>
34484a
Date: Mon, 14 Aug 2017 11:52:39 +1000
34484a
Subject: [PATCH] (perl #131746) avoid undefined behaviour in Copy() etc
34484a
MIME-Version: 1.0
34484a
Content-Type: text/plain; charset=UTF-8
34484a
Content-Transfer-Encoding: 8bit
34484a
34484a
These functions depend on C library functions which have undefined
34484a
behaviour when passed NULL pointers, even when passed a zero 'n' value.
34484a
34484a
Some compilers use this information, ie. assume the pointers are
34484a
non-NULL when optimizing any following code, so we do need to
34484a
prevent such unguarded calls.
34484a
34484a
My initial thought was to add conditionals to each macro to skip the
34484a
call to the library function when n is zero, but this adds a cost to
34484a
every use of these macros, even when the n value is always true.
34484a
34484a
So instead I added asserts() which will give us a much more visible
34484a
indicator of such broken code and revealed the pp_caller and Glob.xs
34484a
issues also patched here.
34484a
34484a
Petr Písař: Ported to 5.26.1 from
34484a
f14cf3632059d421de83cf901c7e849adc1fcd03.
34484a
34484a
Signed-off-by: Petr Písař <ppisar@redhat.com>
34484a
---
34484a
 ext/File-Glob/Glob.xs |  2 +-
34484a
 handy.h               | 14 +++++++-------
34484a
 pp_ctl.c              |  3 ++-
34484a
 pp_hot.c              |  3 ++-
34484a
 4 files changed, 12 insertions(+), 10 deletions(-)
34484a
34484a
diff --git a/ext/File-Glob/Glob.xs b/ext/File-Glob/Glob.xs
34484a
index e0a3681..9779d54 100644
34484a
--- a/ext/File-Glob/Glob.xs
34484a
+++ b/ext/File-Glob/Glob.xs
34484a
@@ -121,7 +121,7 @@ iterate(pTHX_ bool(*globber)(pTHX_ AV *entries, const char *pat, STRLEN len, boo
34484a
 
34484a
     /* chuck it all out, quick or slow */
34484a
     if (gimme == G_ARRAY) {
34484a
-	if (!on_stack) {
34484a
+	if (!on_stack && AvFILLp(entries) + 1) {
34484a
 	    EXTEND(SP, AvFILLp(entries)+1);
34484a
 	    Copy(AvARRAY(entries), SP+1, AvFILLp(entries)+1, SV *);
34484a
 	    SP += AvFILLp(entries)+1;
34484a
diff --git a/handy.h b/handy.h
34484a
index 80f9cf4..88b5b55 100644
34484a
--- a/handy.h
34484a
+++ b/handy.h
34484a
@@ -2409,17 +2409,17 @@ void Perl_mem_log_del_sv(const SV *sv, const char *filename, const int linenumbe
34484a
 #define Safefree(d)	safefree(MEM_LOG_FREE((Malloc_t)(d)))
34484a
 #endif
34484a
 
34484a
-#define Move(s,d,n,t)	(MEM_WRAP_CHECK_(n,t) (void)memmove((char*)(d),(const char*)(s), (n) * sizeof(t)))
34484a
-#define Copy(s,d,n,t)	(MEM_WRAP_CHECK_(n,t) (void)memcpy((char*)(d),(const char*)(s), (n) * sizeof(t)))
34484a
-#define Zero(d,n,t)	(MEM_WRAP_CHECK_(n,t) (void)memzero((char*)(d), (n) * sizeof(t)))
34484a
+#define Move(s,d,n,t)	(MEM_WRAP_CHECK_(n,t) assert(d), assert(s), (void)memmove((char*)(d),(const char*)(s), (n) * sizeof(t)))
34484a
+#define Copy(s,d,n,t)	(MEM_WRAP_CHECK_(n,t) assert(d), assert(s), (void)memcpy((char*)(d),(const char*)(s), (n) * sizeof(t)))
34484a
+#define Zero(d,n,t)	(MEM_WRAP_CHECK_(n,t) assert(d), (void)memzero((char*)(d), (n) * sizeof(t)))
34484a
 
34484a
-#define MoveD(s,d,n,t)	(MEM_WRAP_CHECK_(n,t) memmove((char*)(d),(const char*)(s), (n) * sizeof(t)))
34484a
-#define CopyD(s,d,n,t)	(MEM_WRAP_CHECK_(n,t) memcpy((char*)(d),(const char*)(s), (n) * sizeof(t)))
34484a
+#define MoveD(s,d,n,t)	(MEM_WRAP_CHECK_(n,t) assert(d), assert(s), memmove((char*)(d),(const char*)(s), (n) * sizeof(t)))
34484a
+#define CopyD(s,d,n,t)	(MEM_WRAP_CHECK_(n,t) assert(d), assert(s), memcpy((char*)(d),(const char*)(s), (n) * sizeof(t)))
34484a
 #ifdef HAS_MEMSET
34484a
-#define ZeroD(d,n,t)	(MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)))
34484a
+#define ZeroD(d,n,t)	(MEM_WRAP_CHECK_(n,t) assert(d), memzero((char*)(d), (n) * sizeof(t)))
34484a
 #else
34484a
 /* Using bzero(), which returns void.  */
34484a
-#define ZeroD(d,n,t)	(MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)),d)
34484a
+#define ZeroD(d,n,t)	(MEM_WRAP_CHECK_(n,t) assert(d), memzero((char*)(d), (n) * sizeof(t)),d)
34484a
 #endif
34484a
 
34484a
 #define PoisonWith(d,n,t,b)	(MEM_WRAP_CHECK_(n,t) (void)memset((char*)(d), (U8)(b), (n) * sizeof(t)))
34484a
diff --git a/pp_ctl.c b/pp_ctl.c
34484a
index 15c193b..f1c57bc 100644
34484a
--- a/pp_ctl.c
34484a
+++ b/pp_ctl.c
34484a
@@ -1971,7 +1971,8 @@ PP(pp_caller)
34484a
 
34484a
 	if (AvMAX(PL_dbargs) < AvFILLp(ary) + off)
34484a
 	    av_extend(PL_dbargs, AvFILLp(ary) + off);
34484a
-	Copy(AvALLOC(ary), AvARRAY(PL_dbargs), AvFILLp(ary) + 1 + off, SV*);
34484a
+        if (AvFILLp(ary) + 1 + off)
34484a
+            Copy(AvALLOC(ary), AvARRAY(PL_dbargs), AvFILLp(ary) + 1 + off, SV*);
34484a
 	AvFILLp(PL_dbargs) = AvFILLp(ary) + off;
34484a
     }
34484a
     mPUSHi(CopHINTS_get(cx->blk_oldcop));
34484a
diff --git a/pp_hot.c b/pp_hot.c
34484a
index 5899413..66b79ea 100644
34484a
--- a/pp_hot.c
34484a
+++ b/pp_hot.c
34484a
@@ -4138,7 +4138,8 @@ PP(pp_entersub)
34484a
                 AvARRAY(av) = ary;
34484a
             }
34484a
 
34484a
-	    Copy(MARK+1,AvARRAY(av),items,SV*);
34484a
+            if (items)
34484a
+                Copy(MARK+1,AvARRAY(av),items,SV*);
34484a
 	    AvFILLp(av) = items - 1;
34484a
 	}
34484a
 	if (UNLIKELY((cx->blk_u16 & OPpENTERSUB_LVAL_MASK) == OPpLVAL_INTRO &&
34484a
-- 
34484a
2.13.6
34484a