Fix two cases of buffer overflow in the lexer.
[p5sagit/p5-mst-13.2.git] / lib / Hash / Util.t
CommitLineData
49293501 1#!/usr/bin/perl -Tw
2
3BEGIN {
4 if( $ENV{PERL_CORE} ) {
5 @INC = '../lib';
6 chdir 't';
7 }
8}
0cd24ecf 9use Test::More tests => 61;
10use strict;
49293501 11
12my @Exported_Funcs;
13BEGIN {
14 @Exported_Funcs = qw(lock_keys unlock_keys
15 lock_value unlock_value
16 lock_hash unlock_hash
17 );
18 use_ok 'Hash::Util', @Exported_Funcs;
19}
20foreach my $func (@Exported_Funcs) {
21 can_ok __PACKAGE__, $func;
22}
23
24my %hash = (foo => 42, bar => 23, locked => 'yep');
25lock_keys(%hash);
26eval { $hash{baz} = 99; };
2393f1b9 27like( $@, qr/^Attempt to access disallowed key 'baz' in a restricted hash/,
49293501 28 'lock_keys()');
29is( $hash{bar}, 23 );
30ok( !exists $hash{baz} );
31
32delete $hash{bar};
33ok( !exists $hash{bar} );
34$hash{bar} = 69;
35is( $hash{bar}, 69 );
36
37eval { () = $hash{i_dont_exist} };
2393f1b9 38like( $@, qr/^Attempt to access disallowed key 'i_dont_exist' in a restricted hash/ );
49293501 39
40lock_value(%hash, 'locked');
41eval { print "# oops" if $hash{four} };
2393f1b9 42like( $@, qr/^Attempt to access disallowed key 'four' in a restricted hash/ );
49293501 43
44eval { $hash{"\x{2323}"} = 3 };
2393f1b9 45like( $@, qr/^Attempt to access disallowed key '(.*)' in a restricted hash/,
49293501 46 'wide hex key' );
47
48eval { delete $hash{locked} };
2393f1b9 49like( $@, qr/^Attempt to delete readonly key 'locked' from a restricted hash/,
49293501 50 'trying to delete a locked key' );
51eval { $hash{locked} = 42; };
52like( $@, qr/^Modification of a read-only value attempted/,
53 'trying to change a locked key' );
54is( $hash{locked}, 'yep' );
55
56eval { delete $hash{I_dont_exist} };
2393f1b9 57like( $@, qr/^Attempt to delete disallowed key 'I_dont_exist' from a restricted hash/,
49293501 58 'trying to delete a key that doesnt exist' );
59
60ok( !exists $hash{I_dont_exist} );
61
62unlock_keys(%hash);
63$hash{I_dont_exist} = 42;
64is( $hash{I_dont_exist}, 42, 'unlock_keys' );
65
66eval { $hash{locked} = 42; };
67like( $@, qr/^Modification of a read-only value attempted/,
68 ' individual key still readonly' );
69eval { delete $hash{locked} },
70is( $@, '', ' but can be deleted :(' );
71
72unlock_value(%hash, 'locked');
73$hash{locked} = 42;
74is( $hash{locked}, 42, 'unlock_value' );
75
76
77TODO: {
78# local $TODO = 'assigning to a hash screws with locked keys';
79
80 my %hash = ( foo => 42, locked => 23 );
81
82 lock_keys(%hash);
83 lock_value(%hash, 'locked');
84 eval { %hash = ( wubble => 42 ) }; # we know this will bomb
2393f1b9 85 like( $@, qr/^Attempt to clear a restricted hash/ );
49293501 86
87 eval { unlock_value(%hash, 'locked') }; # but this shouldn't
88 is( $@, '', 'unlock_value() after denied assignment' );
89
90 is_deeply( \%hash, { foo => 42, locked => 23 },
91 'hash should not be altered by denied assignment' );
92 unlock_keys(%hash);
93}
94
95{
96 my %hash = (KEY => 'val', RO => 'val');
97 lock_keys(%hash);
98 lock_value(%hash, 'RO');
99
100 eval { %hash = (KEY => 1) };
2393f1b9 101 like( $@, qr/^Attempt to clear a restricted hash/ );
49293501 102}
103
104# TODO: This should be allowed but it might require putting extra
105# code into aassign.
106{
107 my %hash = (KEY => 1, RO => 2);
108 lock_keys(%hash);
109 eval { %hash = (KEY => 1, RO => 2) };
2393f1b9 110 like( $@, qr/^Attempt to clear a restricted hash/ );
49293501 111}
112
113
114
115{
116 my %hash = ();
117 lock_keys(%hash, qw(foo bar));
118 is( keys %hash, 0, 'lock_keys() w/keyset shouldnt add new keys' );
119 $hash{foo} = 42;
120 is( keys %hash, 1 );
121 eval { $hash{wibble} = 42 };
2393f1b9 122 like( $@, qr/^Attempt to access disallowed key 'wibble' in a restricted hash/,
49293501 123 ' locked');
124
125 unlock_keys(%hash);
126 eval { $hash{wibble} = 23; };
127 is( $@, '', 'unlock_keys' );
128}
129
130
131{
132 my %hash = (foo => 42, bar => undef, baz => 0);
133 lock_keys(%hash, qw(foo bar baz up down));
134 is( keys %hash, 3, 'lock_keys() w/keyset didnt add new keys' );
135 is_deeply( \%hash, { foo => 42, bar => undef, baz => 0 } );
136
137 eval { $hash{up} = 42; };
138 is( $@, '' );
139
140 eval { $hash{wibble} = 23 };
2393f1b9 141 like( $@, qr/^Attempt to access disallowed key 'wibble' in a restricted hash/, ' locked' );
49293501 142}
143
144
145{
146 my %hash = (foo => 42, bar => undef);
147 eval { lock_keys(%hash, qw(foo baz)); };
148 is( $@, sprintf("Hash has key 'bar' which is not in the new key ".
149 "set at %s line %d\n", __FILE__, __LINE__ - 2) );
150}
151
152
153{
154 my %hash = (foo => 42, bar => 23);
155 lock_hash( %hash );
156
29569577 157 ok( Internals::SvREADONLY(%hash) );
158 ok( Internals::SvREADONLY($hash{foo}) );
159 ok( Internals::SvREADONLY($hash{bar}) );
49293501 160
161 unlock_hash ( %hash );
162
29569577 163 ok( !Internals::SvREADONLY(%hash) );
164 ok( !Internals::SvREADONLY($hash{foo}) );
165 ok( !Internals::SvREADONLY($hash{bar}) );
49293501 166}
167
168
169lock_keys(%ENV);
170eval { () = $ENV{I_DONT_EXIST} };
2393f1b9 171like( $@, qr/^Attempt to access disallowed key 'I_DONT_EXIST' in a restricted hash/, 'locked %ENV');
dfd4ef2f 172
173{
174 my %hash;
175
176 lock_keys(%hash, 'first');
177
178 is (scalar keys %hash, 0, "place holder isn't a key");
179 $hash{first} = 1;
180 is (scalar keys %hash, 1, "we now have a key");
181 delete $hash{first};
182 is (scalar keys %hash, 0, "now no key");
183
184 unlock_keys(%hash);
185
186 $hash{interregnum} = 1.5;
187 is (scalar keys %hash, 1, "key again");
188 delete $hash{interregnum};
189 is (scalar keys %hash, 0, "no key again");
190
191 lock_keys(%hash, 'second');
192
193 is (scalar keys %hash, 0, "place holder isn't a key");
194
195 eval {$hash{zeroeth} = 0};
196 like ($@,
197 qr/^Attempt to access disallowed key 'zeroeth' in a restricted hash/,
198 'locked key never mentioned before should fail');
199 eval {$hash{first} = -1};
200 like ($@,
201 qr/^Attempt to access disallowed key 'first' in a restricted hash/,
202 'previously locked place holders should also fail');
203 is (scalar keys %hash, 0, "and therefore there are no keys");
204 $hash{second} = 1;
205 is (scalar keys %hash, 1, "we now have just one key");
0cd24ecf 206 delete $hash{second};
207 is (scalar keys %hash, 0, "back to zero");
208
209 unlock_keys(%hash); # We have deliberately left a placeholder.
210
211 $hash{void} = undef;
212 $hash{nowt} = undef;
213
214 is (scalar keys %hash, 2, "two keys, values both undef");
215
216 lock_keys(%hash);
217
218 is (scalar keys %hash, 2, "still two keys after locking");
219
220 eval {$hash{second} = -1};
221 like ($@,
222 qr/^Attempt to access disallowed key 'second' in a restricted hash/,
223 'previously locked place holders should fail');
224
225 is ($hash{void}, undef,
226 "undef values should not be misunderstood as placeholders");
227 is ($hash{nowt}, undef,
228 "undef values should not be misunderstood as placeholders (again)");
dfd4ef2f 229}