diff options
author | Tony Cook <tony@develop-help.com> | 2013-01-25 09:56:01 +1100 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2013-01-25 10:27:29 +1100 |
commit | b38d579d7e4fdb6e4abade72630ea777d8c509d9 (patch) | |
tree | 7719c50e4f31e149dfa49005720196f901889c69 /ext/PerlIO-scalar | |
parent | 52879d7fcf9b398e46a3b65c2fd169e3ec26f2f7 (diff) | |
download | perl-b38d579d7e4fdb6e4abade72630ea777d8c509d9.tar.gz |
handle reading from a SVf_UTF8 scalar
if the scalar can be downgradable, it is downgraded and the read succeeds.
Otherwise the read fails, producing a warning if enabled and setting
errno/$! to EINVAL.
Diffstat (limited to 'ext/PerlIO-scalar')
-rw-r--r-- | ext/PerlIO-scalar/scalar.xs | 16 | ||||
-rw-r--r-- | ext/PerlIO-scalar/t/scalar.t | 8 |
2 files changed, 17 insertions, 7 deletions
diff --git a/ext/PerlIO-scalar/scalar.xs b/ext/PerlIO-scalar/scalar.xs index d7c7ef69bb..3be9944fcb 100644 --- a/ext/PerlIO-scalar/scalar.xs +++ b/ext/PerlIO-scalar/scalar.xs @@ -6,6 +6,9 @@ #include "perliol.h" +static const char code_point_warning[] = + "Strings with code points over 0xFF may not be mapped into in-memory file handles\n"; + typedef struct { struct _PerlIO base; /* Base "class" info */ SV *var; @@ -54,7 +57,7 @@ PerlIOScalar_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg, } if (SvUTF8(s->var) && !sv_utf8_downgrade(s->var, TRUE)) { if (ckWARN(WARN_UTF8)) - Perl_warner(aTHX_ packWARN(WARN_UTF8), "Strings with code points over 0xFF may not be mapped into in-memory file handles\n"); + Perl_warner(aTHX_ packWARN(WARN_UTF8), code_point_warning); SETERRNO(EINVAL, SS_IVCHAN); SvREFCNT_dec(s->var); s->var = Nullsv; @@ -151,6 +154,17 @@ PerlIOScalar_read(pTHX_ PerlIO *f, void *vbuf, Size_t count) STRLEN len; I32 got; p = SvPV(sv, len); + if (SvUTF8(sv)) { + if (sv_utf8_downgrade(sv, TRUE)) { + p = SvPV_nomg(sv, len); + } + else { + if (ckWARN(WARN_UTF8)) + Perl_warner(aTHX_ packWARN(WARN_UTF8), code_point_warning); + SETERRNO(EINVAL, SS_IVCHAN); + return -1; + } + } got = len - (STRLEN)(s->posn); if (got <= 0) return 0; diff --git a/ext/PerlIO-scalar/t/scalar.t b/ext/PerlIO-scalar/t/scalar.t index 2280fe03f6..3be26c5c8c 100644 --- a/ext/PerlIO-scalar/t/scalar.t +++ b/ext/PerlIO-scalar/t/scalar.t @@ -414,14 +414,13 @@ my $byte_warning = "Strings with code points over 0xFF may not be mapped into in } { # changes after open my $content = "abc"; - ok(open(my $fh, "<", \$content), "open a scalar"); + ok(open(my $fh, "+<", \$content), "open a scalar"); my $tmp; is(read($fh, $tmp, 1), 1, "basic read"); seek($fh, 1, SEEK_SET); $content = "\xA1\xA2\xA3"; utf8::upgrade($content); is(read($fh, $tmp, 1), 1, "read from post-open upgraded scalar"); - local $TODO = "read doesn't handle a post open non-byte scalar"; is($tmp, "\xA2", "check we read the correct value"); seek($fh, 1, SEEK_SET); $content = "\x{101}\x{102}\x{103}"; @@ -432,10 +431,7 @@ my $byte_warning = "Strings with code points over 0xFF may not be mapped into in $! = 0; is(read($fh, $tmp, 1), undef, "read from scalar with >0xff chars"); is(0+$!, EINVAL, "check errno set correctly"); - { - local $TODO; - is_deeply(\@warnings, [], "should be no warning (yet)"); - } + is_deeply(\@warnings, [], "should be no warning (yet)"); use warnings "utf8"; seek($fh, 1, SEEK_SET); is(read($fh, $tmp, 1), undef, "read from scalar with >0xff chars"); |