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