1#!./perl 2 3BEGIN { 4 chdir 't' if -d 't'; 5 require './test.pl'; 6 set_up_inc('../lib'); 7} 8 9use Config; 10 11plan(tests => 78); 12 13 14is(vec($foo,0,1), 0); 15is(length($foo), undef); 16vec($foo,0,1) = 1; 17is(length($foo), 1); 18is(unpack('C',$foo), 1); 19is(vec($foo,0,1), 1); 20 21is(vec($foo,20,1), 0); 22vec($foo,20,1) = 1; 23is(vec($foo,20,1), 1); 24is(length($foo), 3); 25is(vec($foo,1,8), 0); 26vec($foo,1,8) = 0xf1; 27is(vec($foo,1,8), 0xf1); 28is((unpack('C',substr($foo,1,1)) & 255), 0xf1); 29is(vec($foo,2,4), 1);; 30is(vec($foo,3,4), 15); 31vec($Vec, 0, 32) = 0xbaddacab; 32is($Vec, "\xba\xdd\xac\xab"); 33is(vec($Vec, 0, 32), 3135089835); 34 35# ensure vec() handles numericalness correctly 36$foo = $bar = $baz = 0; 37vec($foo = 0,0,1) = 1; 38vec($bar = 0,1,1) = 1; 39$baz = $foo | $bar; 40ok($foo eq "1" && $foo == 1); 41ok($bar eq "2" && $bar == 2); 42ok("$foo $bar $baz" eq "1 2 3"); 43 44# error cases 45 46$x = eval { vec $foo, 0, 3 }; 47like($@, qr/^Illegal number of bits in vec/); 48$@ = undef; 49$x = eval { vec $foo, 0, 0 }; 50like($@, qr/^Illegal number of bits in vec/); 51$@ = undef; 52$x = eval { vec $foo, 0, -13 }; 53like($@, qr/^Illegal number of bits in vec/); 54$@ = undef; 55$x = eval { vec($foo, -1, 4) = 2 }; 56like($@, qr/^Negative offset to vec in lvalue context/); 57$@ = undef; 58ok(! vec('abcd', 7, 8)); 59 60# UTF8 61# N.B. currently curiously coded to circumvent bugs elswhere in UTF8 handling 62 63$foo = "\x{100}" . "\xff\xfe"; 64$x = substr $foo, 1; 65is(vec($x, 0, 8), 255); 66$@ = undef; 67{ 68 no warnings 'deprecated'; 69 eval { vec($foo, 1, 8) }; 70 ok(! $@); 71 $@ = undef; 72 eval { vec($foo, 1, 8) = 13 }; 73 ok(! $@); 74 if ($::IS_EBCDIC) { 75 is($foo, "\x8c\x0d\xff\x8a\x69"); 76 } 77 else { 78 is($foo, "\xc4\x0d\xc3\xbf\xc3\xbe"); 79 } 80} 81$foo = "\x{100}" . "\xff\xfe"; 82$x = substr $foo, 1; 83vec($x, 2, 4) = 7; 84is($x, "\xff\xf7"); 85 86# mixed magic 87 88$foo = "\x61\x62\x63\x64\x65\x66"; 89is(vec(substr($foo, 2, 2), 0, 16), 25444); 90vec(substr($foo, 1,3), 5, 4) = 3; 91is($foo, "\x61\x62\x63\x34\x65\x66"); 92 93# A variation of [perl #20933] 94{ 95 my $s = ""; 96 vec($s, 0, 1) = 0; 97 vec($s, 1, 1) = 1; 98 my @r; 99 $r[$_] = \ vec $s, $_, 1 for (0, 1); 100 ok(!(${ $r[0] } != 0 || ${ $r[1] } != 1)); 101} 102 103 104my $destroyed; 105{ package Class; DESTROY { ++$destroyed; } } 106 107$destroyed = 0; 108{ 109 my $x = ''; 110 vec($x,0,1) = 0; 111 $x = bless({}, 'Class'); 112} 113is($destroyed, 1, 'Timely scalar destruction with lvalue vec'); 114 115use constant roref => \1; 116eval { for (roref) { vec($_,0,1) = 1 } }; 117like($@, qr/^Modification of a read-only value attempted at /, 118 'err msg when modifying read-only refs'); 119 120 121{ 122 # downgradeable utf8 strings should be downgraded before accessing 123 # the byte string. 124 # See the p5p thread with Message-ID: 125 # <CAMx+QJ6SAv05nmpnc7bmp0Wo+sjcx=ssxCcE-P_PZ8HDuCQd9A@mail.gmail.com> 126 127 128 my $x = substr "\x{100}\xff\xfe", 1; # a utf8 string with all ords < 256 129 my $v; 130 $v = vec($x, 0, 8); 131 is($v, 255, "downgraded utf8 try 1"); 132 $v = vec($x, 0, 8); 133 is($v, 255, "downgraded utf8 try 2"); 134} 135 136# [perl #128260] assertion failure with \vec %h, \vec @h 137{ 138 my %h = 1..100; 139 my @a = 1..100; 140 is ${\vec %h, 0, 1}, vec(scalar %h, 0, 1), '\vec %h'; 141 is ${\vec @a, 0, 1}, vec(scalar @a, 0, 1), '\vec @a'; 142} 143 144 145# [perl #130915] heap-buffer-overflow in Perl_do_vecget 146 147{ 148 # ensure that out-of-STRLEN-range offsets are handled correctly. This 149 # partially duplicates some tests above, but those cases are repeated 150 # here for completeness. 151 # 152 # Note that all the 'Out of memory!' errors trapped eval {} are 'fake' 153 # croaks generated by pp_vec() etc when they have detected something 154 # that would have otherwise overflowed. The real 'Out of memory!' 155 # error thrown by safesysrealloc() etc is not trappable. If it were 156 # accidentally triggered in this test script, the script would exit at 157 # that point. 158 159 160 my $s = "abcdefghijklmnopqrstuvwxyz"; 161 my $x; 162 163 # offset is SvIOK_UV 164 165 $x = vec($s, ~0, 8); 166 is($x, 0, "RT 130915: UV_MAX rval"); 167 eval { vec($s, ~0, 8) = 1 }; 168 like($@, qr/^Out of memory!/, "RT 130915: UV_MAX lval"); 169 170 # offset is negative 171 172 $x = vec($s, -1, 8); 173 is($x, 0, "RT 130915: -1 rval"); 174 eval { vec($s, -1, 8) = 1 }; 175 like($@, qr/^Negative offset to vec in lvalue context/, 176 "RT 130915: -1 lval"); 177 178 # offset positive but doesn't fit in a STRLEN 179 180 SKIP: { 181 skip 'IV is no longer than size_t', 2 182 if $Config{ivsize} <= $Config{sizesize}; 183 184 my $size_max = (1 << (8 *$Config{sizesize})) - 1; 185 my $sm2 = $size_max * 2; 186 187 $x = vec($s, $sm2, 8); 188 is($x, 0, "RT 130915: size_max*2 rval"); 189 eval { vec($s, $sm2, 8) = 1 }; 190 like($@, qr/^Out of memory!/, "RT 130915: size_max*2 lval"); 191 } 192 193 # (offset * num-bytes) could overflow 194 195 for my $power (1..3) { 196 my $bytes = (1 << $power); 197 my $biglog2 = $Config{sizesize} * 8 - $power; 198 for my $i (0..1) { 199 my $offset = (1 << $biglog2) - $i; 200 $x = vec($s, $offset, $bytes*8); 201 is($x, 0, "large offset: bytes=$bytes biglog2=$biglog2 i=$i: rval"); 202 eval { vec($s, $offset, $bytes*8) = 1; }; 203 like($@, qr/^Out of memory!/, 204 "large offset: bytes=$bytes biglog2=$biglog2 i=$i: rval"); 205 } 206 } 207} 208 209# Test multi-byte gets partially beyond the end of the string. 210# It's supposed to pretend there is a stream of \0's following the string. 211 212{ 213 my $s = "\x01\x02\x03\x04\x05\x06\x07"; 214 my $s0 = $s . ("\0" x 8); 215 216 for my $bytes (1, 2, 4, 8) { 217 for my $offset (0..$bytes) { 218 if ($Config{ivsize} < $bytes) { 219 pass("skipping multi-byte bytes=$bytes offset=$offset"); 220 next; 221 } 222 no warnings 'portable'; 223 is (vec($s, 8 - $offset, $bytes*8), 224 vec($s0, 8 - $offset, $bytes*8), 225 "multi-byte bytes=$bytes offset=$offset"); 226 } 227 } 228} 229 230# RT #131083 maybe-lvalue out of range should only croak if assigned to 231 232{ 233 sub RT131083 { if ($_[0]) { $_[1] = 1; } $_[1]; } 234 my $s = "abc"; 235 my $off = -1; 236 my $v = RT131083(0, vec($s, $off, 8)); 237 is($v, 0, "RT131083 rval -1"); 238 $v = eval { RT131083(1, vec($s, $off, 8)); }; 239 like($@, qr/Negative offset to vec in lvalue context/, "RT131083 lval -1"); 240 241 $off = ~0; 242 my $v = RT131083(0, vec($s, $off, 8)); 243 is($v, 0, "RT131083 rval ~0"); 244 $v = eval { RT131083(1, vec($s, $off, 8)); }; 245 like($@, qr/Out of memory!/, "RT131083 lval ~0"); 246} 247