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