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