summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-01-31 12:57:09 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-01-31 12:57:09 -0800
commitfe46cbda823c09f80e4bc48dd93fafb26cc805f6 (patch)
tree0a31624d53759263953496dec82595cc9edaf9d2
parent92c88ef1fd925fb1c768293bd43deb970990e7f3 (diff)
downloadperl-fe46cbda823c09f80e4bc48dd93fafb26cc805f6.tar.gz
[perl #108994] Stop SvPVutf8 from coercing SVs
In shouldn’t destroy globs or references passed to it, or try to coerce them if they are read-only or incoercible. I added tests for SvPVbyte at the same time, even though it was not exhibiting the same problems, as sv_utf8_downgrade doesn’t try to coerce anything. (SvPVbyte has its own set of bugs, which I hope to fix in fifthcoming commits.)
-rw-r--r--MANIFEST1
-rw-r--r--embed.fnc2
-rw-r--r--ext/XS-APItest/APItest.xs14
-rw-r--r--ext/XS-APItest/t/svpv.t19
-rw-r--r--proto.h2
-rw-r--r--sv.c4
6 files changed, 39 insertions, 3 deletions
diff --git a/MANIFEST b/MANIFEST
index ac9fbb06d8..822c9aaad3 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -4003,6 +4003,7 @@ ext/XS-APItest/t/stuff_svcur_bug.t test for a bug in lex_stuff_pvn
ext/XS-APItest/t/sviscow.t Test SvIsCOW
ext/XS-APItest/t/svpeek.t XS::APItest extension
ext/XS-APItest/t/svpv_magic.t Test behaviour of SvPVbyte and get magic
+ext/XS-APItest/t/svpv.t More generic SvPVbyte and SvPVutf8 tests
ext/XS-APItest/t/svsetsv.t Test behaviour of sv_setsv with/without PERL_CORE
ext/XS-APItest/t/swaplabel.t test recursive descent label parsing
ext/XS-APItest/t/swaptwostmts.t test recursive descent statement parsing
diff --git a/embed.fnc b/embed.fnc
index 0be9b59155..19b6b6bec5 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -1211,7 +1211,7 @@ Apd |NV |sv_2nv_flags |NULLOK SV *const sv|const I32 flags
pMd |SV* |sv_2num |NN SV *const sv
Amb |char* |sv_2pv |NULLOK SV *sv|NULLOK STRLEN *lp
Apd |char* |sv_2pv_flags |NULLOK SV *const sv|NULLOK STRLEN *const lp|const I32 flags
-Apd |char* |sv_2pvutf8 |NN SV *const sv|NULLOK STRLEN *const lp
+Apd |char* |sv_2pvutf8 |NN SV *sv|NULLOK STRLEN *const lp
Apd |char* |sv_2pvbyte |NN SV *const sv|NULLOK STRLEN *const lp
Ap |char* |sv_pvn_nomg |NN SV* sv|NULLOK STRLEN* lp
Amb |UV |sv_2uv |NULLOK SV *sv
diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs
index 01b5b087f8..2c20ec2fab 100644
--- a/ext/XS-APItest/APItest.xs
+++ b/ext/XS-APItest/APItest.xs
@@ -3273,6 +3273,20 @@ CODE:
OUTPUT:
RETVAL
+char *
+SvPVbyte(SV *sv)
+CODE:
+ RETVAL = SvPVbyte_nolen(sv);
+OUTPUT:
+ RETVAL
+
+char *
+SvPVutf8(SV *sv)
+CODE:
+ RETVAL = SvPVutf8_nolen(sv);
+OUTPUT:
+ RETVAL
+
MODULE = XS::APItest PACKAGE = XS::APItest::AUTOLOADtest
diff --git a/ext/XS-APItest/t/svpv.t b/ext/XS-APItest/t/svpv.t
new file mode 100644
index 0000000000..e98df08486
--- /dev/null
+++ b/ext/XS-APItest/t/svpv.t
@@ -0,0 +1,19 @@
+#!perl -w
+
+use Test::More tests => 16;
+
+use XS::APItest;
+
+for my $func ('SvPVbyte', 'SvPVutf8') {
+ $g = *glob;
+ $r = \1;
+ is &$func($g), '*main::glob', "$func(\$glob_copy)";
+ is ref\$g, 'GLOB', "$func(\$glob_copy) does not flatten the glob";
+ is &$func($r), "$r", "$func(\$ref)";
+ is ref\$r, 'REF', "$func(\$ref) does not flatten the ref";
+
+ is &$func(*glob), '*main::glob', "$func(*glob)";
+ is ref\$::{glob}, 'GLOB', "$func(*glob) does not flatten the glob";
+ is &$func($^V), "$^V", "$func(\$ro_ref)";
+ is ref\$^V, 'REF', "$func(\$ro_ref) does not flatten the ref";
+}
diff --git a/proto.h b/proto.h
index b5ae1562bd..4f95c42138 100644
--- a/proto.h
+++ b/proto.h
@@ -3727,7 +3727,7 @@ PERL_CALLCONV char* Perl_sv_2pvbyte(pTHX_ SV *const sv, STRLEN *const lp)
#define PERL_ARGS_ASSERT_SV_2PVBYTE_NOLEN \
assert(sv)
-PERL_CALLCONV char* Perl_sv_2pvutf8(pTHX_ SV *const sv, STRLEN *const lp)
+PERL_CALLCONV char* Perl_sv_2pvutf8(pTHX_ SV *sv, STRLEN *const lp)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_SV_2PVUTF8 \
assert(sv)
diff --git a/sv.c b/sv.c
index be5aec808c..4b37aabbff 100644
--- a/sv.c
+++ b/sv.c
@@ -3050,10 +3050,12 @@ Usually accessed via the C<SvPVutf8> macro.
*/
char *
-Perl_sv_2pvutf8(pTHX_ register SV *const sv, STRLEN *const lp)
+Perl_sv_2pvutf8(pTHX_ register SV *sv, STRLEN *const lp)
{
PERL_ARGS_ASSERT_SV_2PVUTF8;
+ if ((SvTHINKFIRST(sv) && !SvIsCOW(sv)) || isGV_with_GP(sv))
+ sv = sv_mortalcopy(sv);
sv_utf8_upgrade(sv);
return lp ? SvPV(sv,*lp) : SvPV_nolen(sv);
}