summaryrefslogtreecommitdiff
path: root/pp_sys.c
diff options
context:
space:
mode:
authorZefram <zefram@fysh.org>2017-12-22 05:32:41 +0000
committerZefram <zefram@fysh.org>2017-12-22 05:32:41 +0000
commit8fe3452cc6ac7af8c08c2044cd3757018a9c8887 (patch)
tree63d395f3905741a85cb178ee5b10f566e88c17ab /pp_sys.c
parentaecacd448cd91d195bb2413fdd04568438514017 (diff)
downloadperl-8fe3452cc6ac7af8c08c2044cd3757018a9c8887.tar.gz
preserve numericness of system() args on Win32
On Windows there's a nasty variation in the meaning of arguments to Perl's system(), in which a numeric first argument isn't used as part of the command to run, but instead selects between two different operations to perform with the command (whether to wait for the command to complete or not). Therefore the reduction of argument scalars to their operative values in the parent process, which was added in commit 64def2aeaeb63f92dadc6dfa33486c1d7b311963, needs to preserve numericness of arguments on Windows. Fixes [perl #132633].
Diffstat (limited to 'pp_sys.c')
-rw-r--r--pp_sys.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/pp_sys.c b/pp_sys.c
index beb60da4c6..0649794104 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -4393,12 +4393,39 @@ PP(pp_system)
# endif
while (++MARK <= SP) {
- SV *origsv = *MARK;
+ SV *origsv = *MARK, *copysv;
STRLEN len;
char *pv;
- pv = SvPV(origsv, len);
- *MARK = newSVpvn_flags(pv, len,
- (SvFLAGS(origsv) & SVf_UTF8) | SVs_TEMP);
+ SvGETMAGIC(origsv);
+#ifdef WIN32
+ /*
+ * Because of a nasty platform-specific variation on the meaning
+ * of arguments to this op, we must preserve numeric arguments
+ * as numeric, not just retain the string value.
+ */
+ if (SvNIOK(origsv) || SvNIOKp(origsv)) {
+ copysv = newSV_type(SVt_PVNV);
+ sv_2mortal(copysv);
+ if (SvPOK(origsv) || SvPOKp(origsv)) {
+ pv = SvPV_nomg(origsv, len);
+ sv_setpvn(copysv, pv, len);
+ SvPOK_off(copysv);
+ }
+ if (SvIOK(origsv) || SvIOKp(origsv))
+ SvIV_set(copysv, SvIVX(origsv));
+ if (SvNOK(origsv) || SvNOKp(origsv))
+ SvNV_set(copysv, SvNVX(origsv));
+ SvFLAGS(copysv) |= SvFLAGS(origsv) &
+ (SVf_IOK|SVf_NOK|SVf_POK|SVp_IOK|SVp_NOK|SVp_POK|
+ SVf_UTF8|SVf_IVisUV);
+ } else
+#endif
+ {
+ pv = SvPV_nomg(origsv, len);
+ copysv = newSVpvn_flags(pv, len,
+ (SvFLAGS(origsv) & SVf_UTF8) | SVs_TEMP);
+ }
+ *MARK = copysv;
}
MARK = ORIGMARK;