|
|
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 |
|