This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[rt #111730] don't use I32 for offsets in vec()
authorTony Cook <tony@develop-help.com>
Fri, 23 Mar 2012 23:27:52 +0000 (00:27 +0100)
committerFather Chrysostomos <sprout@cpan.org>
Tue, 22 May 2012 00:51:53 +0000 (17:51 -0700)
do_vecset() do_vecget() used I32 for the offset, which meant that
offsets outside the -2Gb - +2Gb offset were truncated, resulting in
various misbehaviours.

doop.c
embed.fnc
proto.h
t/bigmem/vec.t

diff --git a/doop.c b/doop.c
index f130477..a562536 100644 (file)
--- a/doop.c
+++ b/doop.c
@@ -760,7 +760,7 @@ Perl_do_sprintf(pTHX_ SV *sv, I32 len, SV **sarg)
 
 /* currently converts input to bytes if possible, but doesn't sweat failure */
 UV
 
 /* currently converts input to bytes if possible, but doesn't sweat failure */
 UV
-Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
+Perl_do_vecget(pTHX_ SV *sv, SSize_t offset, int size)
 {
     dVAR;
     STRLEN srclen, len, uoffset, bitoffs = 0;
 {
     dVAR;
     STRLEN srclen, len, uoffset, bitoffs = 0;
@@ -908,8 +908,8 @@ void
 Perl_do_vecset(pTHX_ SV *sv)
 {
     dVAR;
 Perl_do_vecset(pTHX_ SV *sv)
 {
     dVAR;
-    register I32 offset, bitoffs = 0;
-    register I32 size;
+    register SSize_t offset, bitoffs = 0;
+    register int size;
     register unsigned char *s;
     register UV lval;
     I32 mask;
     register unsigned char *s;
     register UV lval;
     I32 mask;
index 5379121..b637124 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -379,7 +379,7 @@ pR  |Off_t  |do_tell        |NN GV* gv
 : Defined in doop.c, used only in pp.c
 p      |I32    |do_trans       |NN SV* sv
 : Used in my.c and pp.c
 : Defined in doop.c, used only in pp.c
 p      |I32    |do_trans       |NN SV* sv
 : Used in my.c and pp.c
-p      |UV     |do_vecget      |NN SV* sv|I32 offset|I32 size
+p      |UV     |do_vecget      |NN SV* sv|SSize_t offset|int size
 : Defined in doop.c, used only in mg.c (with /* XXX slurp this routine */)
 p      |void   |do_vecset      |NN SV* sv
 : Defined in doop.c, used only in pp.c
 : Defined in doop.c, used only in mg.c (with /* XXX slurp this routine */)
 p      |void   |do_vecset      |NN SV* sv
 : Defined in doop.c, used only in pp.c
diff --git a/proto.h b/proto.h
index eab2626..f9327bb 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -893,7 +893,7 @@ PERL_CALLCONV I32   Perl_do_trans(pTHX_ SV* sv)
 #define PERL_ARGS_ASSERT_DO_TRANS      \
        assert(sv)
 
 #define PERL_ARGS_ASSERT_DO_TRANS      \
        assert(sv)
 
-PERL_CALLCONV UV       Perl_do_vecget(pTHX_ SV* sv, I32 offset, I32 size)
+PERL_CALLCONV UV       Perl_do_vecget(pTHX_ SV* sv, SSize_t offset, int size)
                        __attribute__nonnull__(pTHX_1);
 #define PERL_ARGS_ASSERT_DO_VECGET     \
        assert(sv)
                        __attribute__nonnull__(pTHX_1);
 #define PERL_ARGS_ASSERT_DO_VECGET     \
        assert(sv)
index ccdbb9b..bf3c513 100644 (file)
@@ -16,12 +16,11 @@ $Config{ptrsize} >= 8
 plan(7);
 
 # RT #111730: Negative offset to vec in lvalue context
 plan(7);
 
 # RT #111730: Negative offset to vec in lvalue context
-local $::TODO = "RT #111730 - vec uses I32 for offsets";
 
 my $v = "";
 ok(scalar eval { vec($v, 0x80000000, 1) = 1 }, "set a bit at a large offset");
 ok(vec($v, 0x80000000, 1), "check a bit at a large offset");
 
 my $v = "";
 ok(scalar eval { vec($v, 0x80000000, 1) = 1 }, "set a bit at a large offset");
 ok(vec($v, 0x80000000, 1), "check a bit at a large offset");
-{ local $::TODO; # succeeds but shouldn't at this point
+
 ok(scalar eval { vec($v, 0x100000000, 1) = 1 },
    "set a bit at a larger offset");
 ok(vec($v, 0x100000000, 1), "check a bit at a larger offset");
 ok(scalar eval { vec($v, 0x100000000, 1) = 1 },
    "set a bit at a larger offset");
 ok(vec($v, 0x100000000, 1), "check a bit at a larger offset");
@@ -29,7 +28,6 @@ ok(vec($v, 0x100000000, 1), "check a bit at a larger offset");
 # real out of range values
 ok(!eval { vec($v, -0x80000000, 1) = 1 },
    "shouldn't be able to set at a large negative offset");
 # real out of range values
 ok(!eval { vec($v, -0x80000000, 1) = 1 },
    "shouldn't be able to set at a large negative offset");
-}
 ok(!eval { vec($v, -0x100000000, 1) = 1 },
    "shouldn't be able to set at a larger negative offset");
 
 ok(!eval { vec($v, -0x100000000, 1) = 1 },
    "shouldn't be able to set at a larger negative offset");