File Coverage

blib/lib/YAML/PP/Schema/Perl.pm
Criterion Covered Total %
statement 322 331 97.2
branch 76 88 86.3
condition 12 18 66.6
subroutine 64 64 100.0
pod 13 13 100.0
total 487 514 94.7


line stmt bran cond sub pod time code
1 7     7   166631 use strict;
  7         10  
  7         228  
2 7     7   24 use warnings;
  7         11  
  7         553  
3             package YAML::PP::Schema::Perl;
4              
5             our $VERSION = 'v0.39.0'; # VERSION
6              
7 7     7   36 use Scalar::Util qw/ blessed reftype /;
  7         10  
  7         17996  
8              
9             my $qr_prefix;
10             # workaround to avoid growing regexes when repeatedly loading and dumping
11             # e.g. (?^:(?^:regex))
12             {
13             $qr_prefix = qr{\(\?-xism\:};
14             if ($] >= 5.014) {
15             $qr_prefix = qr{\(\?\^(?:[uadl])?\:};
16             }
17             }
18              
19             sub new {
20 6     6 1 192307 my ($class, %args) = @_;
21 6   50     38 my $tags = $args{tags} || [];
22 6   100     26 my $loadcode = $args{loadcode} || 0;
23 6         11 my $dumpcode = $args{dumpcode};
24 6 50       42 $dumpcode = 1 unless defined $dumpcode;
25 6         10 my $classes = $args{classes};
26              
27 6         54 my $self = bless {
28             tags => $tags,
29             loadcode => $loadcode,
30             dumpcode => $dumpcode,
31             classes => $classes,
32             }, $class;
33             }
34              
35             sub register {
36 24     24 1 65 my ($self, %args) = @_;
37 24         44 my $schema = $args{schema};
38              
39 24         25 my $tags;
40 24         30 my $loadcode = 0;
41 24         42 my $dumpcode = 1;
42 24         30 my $classes;
43 24 100       53 if (blessed($self)) {
44 6         28 $tags = $self->{tags};
45 6 50       21 @$tags = ('!perl') unless @$tags;
46 6         9 $loadcode = $self->{loadcode};
47 6         9 $dumpcode = $self->{dumpcode};
48 6         10 $classes = $self->{classes};
49             }
50             else {
51 18         28 my $options = $args{options};
52 18         23 my $tagtype = '!perl';
53 18         29 for my $option (@$options) {
54 12 100       45 if ($option =~ m/^tags?=(.+)$/) {
    100          
    50          
55 7         18 $tagtype = $1;
56             }
57             elsif ($option eq '+loadcode') {
58 4         5 $loadcode = 1;
59             }
60             elsif ($option eq '-dumpcode') {
61 1         2 $dumpcode = 0;
62             }
63             }
64 18         50 $tags = [split m/\+/, $tagtype];
65             }
66              
67              
68 24         57 my $perl_tag;
69             my %tagtypes;
70 24         0 my @perl_tags;
71 24         36 for my $type (@$tags) {
72 28 100       46 if ($type eq '!perl') {
    50          
73 22   66     77 $perl_tag ||= $type;
74 22         32 push @perl_tags, '!perl';
75             }
76             elsif ($type eq '!!perl') {
77 6   100     16 $perl_tag ||= 'tag:yaml.org,2002:perl';
78 6         8 push @perl_tags, 'tag:yaml.org,2002:perl';
79             }
80             else {
81 0         0 die "Invalid tagtype '$type'";
82             }
83 28         142 $tagtypes{ $type } = 1;
84             }
85              
86 24         32 my $perl_regex = '!perl';
87 24 100 100     110 if ($tagtypes{'!perl'} and $tagtypes{'!!perl'}) {
    100          
    50          
88 4         8 $perl_regex = '(?:tag:yaml\\.org,2002:|!)perl';
89             }
90             elsif ($tagtypes{'!perl'}) {
91 18         25 $perl_regex = '!perl';
92             }
93             elsif ($tagtypes{'!!perl'}) {
94 2         3 $perl_regex = 'tag:yaml\\.org,2002:perl';
95             }
96              
97 24         100 my $class_regex = qr{.+};
98 24         33 my $no_objects = 0;
99 24 100       44 if ($classes) {
100 5 100       11 if (@$classes) {
101 1         6 $class_regex = '(' . join( '|', map "\Q$_\E", @$classes ) . ')';
102             }
103             else {
104 4         7 $no_objects = 1;
105 4         6 $class_regex = '';
106             }
107             }
108              
109             # Code
110 24 100       51 if ($loadcode) {
111             my $load_code = sub {
112 6     6   11 my ($constructor, $event) = @_;
113 6         30 return $self->evaluate_code($event->{value});
114 5         15 };
115             my $load_code_blessed = sub {
116 6     6   14 my ($constructor, $event) = @_;
117 6         13 my $class = $event->{tag};
118 6         99 $class =~ s{^$perl_regex/code:}{};
119 6         29 my $sub = $self->evaluate_code($event->{value});
120 4         18 return $self->object($sub, $class);
121 5         20 };
122             $schema->add_resolver(
123             tag => "$_/code",
124             match => [ all => $load_code],
125             implicit => 0,
126 5         21 ) for @perl_tags;
127 5         188 $schema->add_resolver(
128             tag => qr{^$perl_regex/code:$class_regex$},
129             match => [ all => $load_code_blessed ],
130             implicit => 0,
131             );
132 5 100       27 $schema->add_resolver(
133             tag => qr{^$perl_regex/code:.+},
134             match => [ all => $load_code ],
135             implicit => 0,
136             ) if $no_objects;
137             }
138             else {
139 19     3   61 my $loadcode_dummy = sub { return sub {} };
  3         14  
140             my $loadcode_blessed_dummy = sub {
141 2     2   4 my ($constructor, $event) = @_;
142 2         6 my $class = $event->{tag};
143 2         20 $class =~ s{^$perl_regex/code:}{};
144 2         12 return $self->object(sub {}, $class);
145 19         66 };
146             $schema->add_resolver(
147             tag => "$_/code",
148             match => [ all => $loadcode_dummy ],
149             implicit => 0,
150 19         113 ) for @perl_tags;
151 19         340 $schema->add_resolver(
152             tag => qr{^$perl_regex/code:$class_regex$},
153             match => [ all => $loadcode_blessed_dummy ],
154             implicit => 0,
155             );
156 19         241 $schema->add_resolver(
157             tag => qr{^$perl_regex/code:.+},
158             match => [ all => $loadcode_dummy ],
159             implicit => 0,
160             );
161             }
162              
163             # Glob
164             my $load_glob = sub {
165 8     8   14 my $value = undef;
166 8         17 return \$value;
167 24         123 };
168             my $load_glob_blessed = sub {
169 2     2   4 my ($constructor, $event) = @_;
170 2         3 my $class = $event->{tag};
171 2         21 $class =~ s{^$perl_regex/glob:}{};
172 2         3 my $value = undef;
173 2         9 return $self->object(\$value, $class);
174 24         74 };
175              
176             $schema->add_mapping_resolver(
177             tag => "$_/glob",
178             on_create => $load_glob,
179             on_data => sub {
180 6     6   12 my ($constructor, $ref, $list) = @_;
181 6         30 $$ref = $self->construct_glob($list);
182             },
183 24         145 ) for @perl_tags;
184 24 100       69 if ($no_objects) {
185             $schema->add_mapping_resolver(
186             tag => qr{^$perl_regex/glob:.+$},
187             on_create => $load_glob,
188             on_data => sub {
189 2     2   5 my ($constructor, $ref, $list) = @_;
190 2         11 $$ref = $self->construct_glob($list);
191             },
192 4         46 );
193             }
194             else {
195             $schema->add_mapping_resolver(
196             tag => qr{^$perl_regex/glob:$class_regex$},
197             on_create => $load_glob_blessed,
198             on_data => sub {
199 2     2   4 my ($constructor, $ref, $list) = @_;
200 2         10 $$$ref = $self->construct_glob($list);
201             },
202 20         289 );
203             }
204              
205             # Regex
206             my $load_regex = sub {
207 5     5   10 my ($constructor, $event) = @_;
208 5         25 return $self->construct_regex($event->{value});
209 24         67 };
210             my $load_regex_dummy = sub {
211 2     2   5 my ($constructor, $event) = @_;
212 2         6 return $event->{value};
213 24         267 };
214             my $load_regex_blessed = sub {
215 6     6   14 my ($constructor, $event) = @_;
216 6         13 my $class = $event->{tag};
217 6         115 $class =~ s{^$perl_regex/regexp:}{};
218 6         32 my $qr = $self->construct_regex($event->{value});
219 6         21 return $self->object($qr, $class);
220 24         84 };
221             $schema->add_resolver(
222             tag => "$_/regexp",
223             match => [ all => $load_regex ],
224             implicit => 0,
225 24         85 ) for @perl_tags;
226 24         269 $schema->add_resolver(
227             tag => qr{^$perl_regex/regexp:$class_regex$},
228             match => [ all => $load_regex_blessed ],
229             implicit => 0,
230             );
231 24         251 $schema->add_resolver(
232             tag => qr{^$perl_regex/regexp:.*$},
233             match => [ all => $load_regex_dummy ],
234             implicit => 0,
235             );
236              
237 24     7   63 my $load_sequence = sub { return [] };
  7         19  
238             my $load_sequence_blessed = sub {
239 13     13   24 my ($constructor, $event) = @_;
240 13         27 my $class = $event->{tag};
241 13         150 $class =~ s{^$perl_regex/array:}{};
242 13         91 return $self->object([], $class);
243 24         76 };
244             $schema->add_sequence_resolver(
245             tag => "$_/array",
246             on_create => $load_sequence,
247 24         146 ) for @perl_tags;
248 24         290 $schema->add_sequence_resolver(
249             tag => qr{^$perl_regex/array:$class_regex$},
250             on_create => $load_sequence_blessed,
251             );
252 24         179 $schema->add_sequence_resolver(
253             tag => qr{^$perl_regex/array:.+$},
254             on_create => $load_sequence,
255             );# if $no_objects;
256              
257 24     6   97 my $load_mapping = sub { return {} };
  6         26  
258             my $load_mapping_blessed = sub {
259 7     7   16 my ($constructor, $event) = @_;
260 7         15 my $class = $event->{tag};
261 7         108 $class =~ s{^$perl_regex/hash:}{};
262 7         41 return $self->object({}, $class);
263 24         83 };
264             $schema->add_mapping_resolver(
265             tag => "$_/hash",
266             on_create => $load_mapping,
267 24         78 ) for @perl_tags;
268 24         279 $schema->add_mapping_resolver(
269             tag => qr{^$perl_regex/hash:$class_regex$},
270             on_create => $load_mapping_blessed,
271             );
272 24         166 $schema->add_mapping_resolver(
273             tag => qr{^$perl_regex/hash:.+$},
274             on_create => $load_mapping,
275             ); # if $no_objects;
276              
277             # Ref
278             my $load_ref = sub {
279 8     8   14 my $value = undef;
280 8         20 return \$value;
281 24         70 };
282             my $load_ref_blessed = sub {
283 7     7   21 my ($constructor, $event) = @_;
284 7         18 my $class = $event->{tag};
285 7         91 $class =~ s{^$perl_regex/ref:}{};
286 7         13 my $value = undef;
287 7         31 return $self->object(\$value, $class);
288 24         72 };
289             $schema->add_mapping_resolver(
290             tag => "$_/ref",
291             on_create => $load_ref,
292             on_data => sub {
293 6     6   11 my ($constructor, $ref, $list) = @_;
294 6         28 $$$ref = $self->construct_ref($list);
295             },
296 24         152 ) for @perl_tags;
297             $schema->add_mapping_resolver(
298             tag => qr{^$perl_regex/ref:$class_regex$},
299             on_create => $load_ref_blessed,
300             on_data => sub {
301 7     7   15 my ($constructor, $ref, $list) = @_;
302 7         27 $$$ref = $self->construct_ref($list);
303             },
304 24         342 );
305             $schema->add_mapping_resolver(
306             tag => qr{^$perl_regex/ref:.+$},
307             on_create => $load_ref,
308             on_data => sub {
309 2     2   4 my ($constructor, $ref, $list) = @_;
310 2         8 $$$ref = $self->construct_ref($list);
311             },
312 24         192 ); # if $no_objects;
313              
314             # Scalar ref
315             my $load_scalar_ref = sub {
316 8     8   9 my $value = undef;
317 8         21 return \$value;
318 24         64 };
319             my $load_scalar_ref_blessed = sub {
320 7     7   13 my ($constructor, $event) = @_;
321 7         16 my $class = $event->{tag};
322 7         96 $class =~ s{^$perl_regex/scalar:}{};
323 7         11 my $value = undef;
324 7         31 return $self->object(\$value, $class);
325 24         65 };
326             $schema->add_mapping_resolver(
327             tag => "$_/scalar",
328             on_create => $load_scalar_ref,
329             on_data => sub {
330 6     6   33 my ($constructor, $ref, $list) = @_;
331 6         27 $$$ref = $self->construct_scalar($list);
332             },
333 24         133 ) for @perl_tags;
334             $schema->add_mapping_resolver(
335             tag => qr{^$perl_regex/scalar:$class_regex$},
336             on_create => $load_scalar_ref_blessed,
337             on_data => sub {
338 7     7   20 my ($constructor, $ref, $list) = @_;
339 7         26 $$$ref = $self->construct_scalar($list);
340             },
341 24         300 );
342             $schema->add_mapping_resolver(
343             tag => qr{^$perl_regex/scalar:.+$},
344             on_create => $load_scalar_ref,
345             on_data => sub {
346 2     2   4 my ($constructor, $ref, $list) = @_;
347 2         5 $$$ref = $self->construct_scalar($list);
348             },
349 24         254 ); # if $no_objects;
350              
351             $schema->add_representer(
352             scalarref => 1,
353             code => sub {
354 4     4   10 my ($rep, $node) = @_;
355 4         11 $node->{tag} = $perl_tag . "/scalar";
356 4         20 $node->{data} = $self->represent_scalar($node->{value});
357             },
358 24         121 );
359             $schema->add_representer(
360             refref => 1,
361             code => sub {
362 4     4   8 my ($rep, $node) = @_;
363 4         11 $node->{tag} = $perl_tag . "/ref";
364 4         18 $node->{data} = $self->represent_ref($node->{value});
365             },
366 24         105 );
367             $schema->add_representer(
368             coderef => 1,
369             code => sub {
370 5     5   10 my ($rep, $node) = @_;
371 5         13 $node->{tag} = $perl_tag . "/code";
372 5 100       26 $node->{data} = $dumpcode ? $self->represent_code($node->{value}) : '{ "DUMMY" }';
373             },
374 24         234 );
375             $schema->add_representer(
376             glob => 1,
377             code => sub {
378 6     6   10 my ($rep, $node) = @_;
379 6         17 $node->{tag} = $perl_tag . "/glob";
380 6         28 $node->{data} = $self->represent_glob($node->{value});
381             },
382 24         114 );
383              
384             $schema->add_representer(
385             class_matches => 1,
386             code => sub {
387 40     40   62 my ($rep, $node) = @_;
388 40         84 my $blessed = blessed $node->{value};
389 40         76 my $tag_blessed = ":$blessed";
390 40 50       447 if ($blessed !~ m/^$class_regex$/) {
391 0         0 $tag_blessed = '';
392             }
393             $node->{tag} = sprintf "$perl_tag/%s%s",
394 40         253 lc($node->{reftype}), $tag_blessed;
395 40 100       218 if ($node->{reftype} eq 'HASH') {
    100          
    100          
    100          
    100          
    100          
    50          
396 6         15 $node->{data} = $node->{value};
397             }
398             elsif ($node->{reftype} eq 'ARRAY') {
399 10         22 $node->{data} = $node->{value};
400             }
401              
402             # Fun with regexes in perl versions!
403             elsif ($node->{reftype} eq 'REGEXP') {
404 8 100       21 if ($blessed eq 'Regexp') {
405 4         8 $node->{tag} = $perl_tag . "/regexp";
406             }
407 8         38 $node->{data} = $self->represent_regex($node->{value});
408             }
409             elsif ($node->{reftype} eq 'SCALAR') {
410              
411             # in perl <= 5.10 regex reftype(regex) was SCALAR
412 4 50 33     21 if ($blessed eq 'Regexp') {
    50 33        
413 0         0 $node->{tag} = $perl_tag . '/regexp';
414 0         0 $node->{data} = $self->represent_regex($node->{value});
415             }
416              
417             # In perl <= 5.10 there seemed to be no better pure perl
418             # way to detect a blessed regex?
419             elsif (
420             $] <= 5.010001
421 0         0 and not defined ${ $node->{value} }
422             and $node->{value} =~ m/^\(\?/
423             ) {
424 0         0 $node->{tag} = $perl_tag . '/regexp' . $tag_blessed;
425 0         0 $node->{data} = $self->represent_regex($node->{value});
426             }
427             else {
428             # phew, just a simple scalarref
429 4         21 $node->{data} = $self->represent_scalar($node->{value});
430             }
431             }
432             elsif ($node->{reftype} eq 'REF') {
433 4         20 $node->{data} = $self->represent_ref($node->{value});
434             }
435              
436             elsif ($node->{reftype} eq 'CODE') {
437 5 100       23 $node->{data} = $dumpcode ? $self->represent_code($node->{value}) : '{ "DUMMY" }';
438             }
439             elsif ($node->{reftype} eq 'GLOB') {
440 3         10 $node->{data} = $self->represent_glob($node->{value});
441             }
442             else {
443 0         0 die "Reftype '$node->{reftype}' not implemented";
444             }
445              
446 40         161 return 1;
447             },
448 24         257 );
449 24         207 return;
450             }
451              
452             sub evaluate_code {
453 12     12 1 28 my ($self, $code) = @_;
454 12 100       73 unless ($code =~ m/^ \s* \{ .* \} \s* \z/xs) {
455 2         24 die "Malformed code";
456             }
457 10         27 $code = "sub $code";
458 10     1   758 my $sub = eval $code;
  1     1   8  
  1     1   1  
  1     1   152  
  1     1   9  
  1     1   2  
  1     1   124  
  1     1   6  
  1     1   1  
  1     1   89  
  1     1   6  
  1     1   2  
  1     1   49  
  1     1   7  
  1     1   2  
  1     1   67  
  1         4  
  1         2  
  1         52  
  1         6  
  1         2  
  1         47  
  1         4  
  1         1  
  1         63  
  1         7  
  1         2  
  1         60  
  1         5  
  1         1  
  1         54  
  1         8  
  1         1  
  1         55  
  1         25  
  1         2  
  1         54  
  1         9  
  1         2  
  1         52  
  1         4  
  1         1  
  1         54  
  1         8  
  1         2  
  1         73  
  1         4  
  1         1  
  1         50  
459 10 100       38 if ($@) {
460 2         20 die "Couldn't eval code: $@>>$code<<";
461             }
462 8         28 return $sub;
463             }
464              
465             sub construct_regex {
466 11     11 1 27 my ($self, $regex) = @_;
467 11 100       98 if ($regex =~ m/^$qr_prefix(.*)\)\z/s) {
468 2         5 $regex = $1;
469             }
470 11         134 my $qr = qr{$regex};
471 11         32 return $qr;
472             }
473              
474             sub construct_glob {
475 10     10 1 20 my ($self, $list) = @_;
476 10 50       26 if (@$list % 2) {
477 0         0 die "Unexpected data in perl/glob construction";
478             }
479 10         87 my %globdata = @$list;
480 10 100       40 my $name = delete $globdata{NAME} or die "Missing NAME in perl/glob";
481 9         19 my $pkg = delete $globdata{PACKAGE};
482 9 100       21 $pkg = 'main' unless defined $pkg;
483 9         28 my @allowed = qw(SCALAR ARRAY HASH CODE IO);
484 9         24 delete @globdata{ @allowed };
485 9 100       19 if (my @keys = keys %globdata) {
486 1         16 die "Unexpected keys in perl/glob: @keys";
487             }
488 7     7   48 no strict 'refs';
  7         14  
  7         3202  
489 8         14 return *{"${pkg}::$name"};
  8         65  
490             }
491              
492             sub construct_scalar {
493 30     30 1 53 my ($self, $list) = @_;
494 30 100       62 if (@$list != 2) {
495 4         42 die "Unexpected data in perl/scalar construction";
496             }
497 26         48 my ($key, $value) = @$list;
498 26 100       64 unless ($key eq '=') {
499 4         46 die "Unexpected data in perl/scalar construction";
500             }
501 22         54 return $value;
502             }
503              
504             sub construct_ref {
505 15     15 1 36 &construct_scalar;
506             }
507              
508             sub represent_scalar {
509 16     16 1 30 my ($self, $value) = @_;
510 16         68 return { '=' => $$value };
511             }
512              
513             sub represent_ref {
514 8     8 1 17 &represent_scalar;
515             }
516              
517             sub represent_code {
518 8     8 1 17 my ($self, $code) = @_;
519 8         56 require B::Deparse;
520 8         405 my $deparse = B::Deparse->new("-p", "-sC");
521 8         14860 return $deparse->coderef2text($code);
522             }
523              
524              
525             my @stats = qw/ device inode mode links uid gid rdev size
526             atime mtime ctime blksize blocks /;
527             sub represent_glob {
528 9     9 1 20 my ($self, $glob) = @_;
529 9         9 my %glob;
530 9         20 for my $type (qw/ PACKAGE NAME SCALAR ARRAY HASH CODE IO /) {
531 63         56 my $value = *{ $glob }{ $type };
  63         89  
532 63 100       109 if ($type eq 'SCALAR') {
    100          
533 9         15 $value = $$value;
534             }
535             elsif ($type eq 'IO') {
536 9 100       15 if (defined $value) {
537 5         8 undef $value;
538 5         11 $value->{stat} = {};
539 5 50       6 if ($value->{fileno} = fileno(*{ $glob })) {
  5         19  
540 5         7 @{ $value->{stat} }{ @stats } = stat(*{ $glob });
  5         55  
  5         118  
541 5         10 $value->{tell} = tell *{ $glob };
  5         18  
542             }
543             }
544             }
545 63 100       110 $glob{ $type } = $value if defined $value;
546             }
547 9         35 return \%glob;
548             }
549              
550             sub represent_regex {
551 8     8 1 15 my ($self, $regex) = @_;
552 8         17 $regex = "$regex";
553 8 50       91 if ($regex =~ m/^$qr_prefix(.*)\)\z/s) {
554 8         20 $regex = $1;
555             }
556 8         20 return $regex;
557             }
558              
559             sub object {
560 48     48 1 102 my ($self, $data, $class) = @_;
561 48         197 return bless $data, $class;
562             }
563              
564             1;
565              
566             __END__
567              
568             =pod
569              
570             =encoding utf-8
571              
572             =head1 NAME
573              
574             YAML::PP::Schema::Perl - Schema for serializing perl objects and special types
575              
576             =head1 SYNOPSIS
577              
578             use YAML::PP;
579             # This can be dangerous when loading untrusted YAML!
580             my $yp = YAML::PP->new( schema => [qw/ + Perl /] );
581             # or
582             my $yp = YAML::PP->new( schema => [qw/ Core Perl /] );
583             my $yaml = $yp->dump_string(sub { return 23 });
584              
585             # loading code references
586             # This is very dangerous when loading untrusted YAML!!
587             my $yp = YAML::PP->new( schema => [qw/ + Perl +loadcode /] );
588             my $code = $yp->load_string(<<'EOM');
589             --- !perl/code |
590             {
591             use 5.010;
592             my ($name) = @_;
593             say "Hello $name!";
594             }
595             EOM
596             $code->("Ingy");
597              
598             =head1 DESCRIPTION
599              
600             This schema allows you to load and dump perl objects and special types.
601              
602             Please note that loading objects of arbitrary classes can be dangerous
603             in Perl. You have to load the modules yourself, but if an exploitable module
604             is loaded and an object is created, its C<DESTROY> method will be called
605             when the object falls out of scope. L<File::Temp> is an example that can
606             be exploitable and might remove arbitrary files.
607              
608             Dumping code references is on by default, but not loading (because that is
609             easily exploitable since it's using string C<eval>).
610              
611             =head2 Tag Styles
612              
613             You can define the style of tags you want to support:
614              
615             my $yp_perl_two_one = YAML::PP->new(
616             schema => [qw/ + Perl tags=!!perl+!perl /],
617             );
618              
619             =over
620              
621             =item C<!perl> (default)
622              
623             Only C<!perl/type> tags are supported.
624              
625             =item C<!!perl>
626              
627             Only C<!!perl/type> tags are supported.
628              
629             =item C<!perl+!!perl>
630              
631             Both C<!perl/type> and C<!!perl/tag> are supported when loading. When dumping,
632             C<!perl/type> is used.
633              
634             =item C<!!perl+!perl>
635              
636             Both C<!perl/type> and C<!!perl/tag> are supported when loading. When dumping,
637             C<!!perl/type> is used.
638              
639             =back
640              
641             L<YAML>.pm, L<YAML::Syck> and L<YAML::XS> are using C<!!perl/type> when dumping.
642              
643             L<YAML>.pm and L<YAML::Syck> are supporting both C<!perl/type> and
644             C<!!perl/type> when loading. L<YAML::XS> currently only supports the latter.
645              
646             =head2 Allow only certain classes
647              
648             Since v0.017
649              
650             Blessing arbitrary objects can be dangerous. Maybe you want to allow blessing
651             only specific classes and ignore others. For this you have to instantiate
652             a Perl Schema object first and use the C<classes> option.
653              
654             Currently it only allows a list of strings:
655              
656             my $perl = YAML::PP::Schema::Perl->new(
657             classes => ['Foo', 'Bar'],
658             );
659             my $yp = YAML::PP::Perl->new(
660             schema => [qw/ + /, $perl],
661             );
662              
663             Allowed classes will be loaded and dumped as usual. The others will be ignored.
664              
665             If you want to allow no objects at all, pass an empty array ref.
666              
667              
668             =cut
669              
670             =head2 EXAMPLES
671              
672             This is a list of the currently supported types and how they are dumped into
673             YAML:
674              
675             =cut
676              
677             ### BEGIN EXAMPLE
678              
679             =pod
680              
681             =over 4
682              
683             =item array
684              
685             # Code
686             [
687             qw/ one two three four /
688             ]
689              
690              
691             # YAML
692             ---
693             - one
694             - two
695             - three
696             - four
697              
698              
699             =item array_blessed
700              
701             # Code
702             bless [
703             qw/ one two three four /
704             ], "Just::An::Arrayref"
705              
706              
707             # YAML
708             --- !perl/array:Just::An::Arrayref
709             - one
710             - two
711             - three
712             - four
713              
714              
715             =item circular
716              
717             # Code
718             my $circle = bless [ 1, 2 ], 'Circle';
719             push @$circle, $circle;
720             $circle;
721              
722              
723             # YAML
724             --- &1 !perl/array:Circle
725             - 1
726             - 2
727             - *1
728              
729              
730             =item coderef
731              
732             # Code
733             sub {
734             my (%args) = @_;
735             return $args{x} + $args{y};
736             }
737              
738              
739             # YAML
740             --- !perl/code |-
741             {
742             use warnings;
743             use strict;
744             (my(%args) = @_);
745             (return ($args{'x'} + $args{'y'}));
746             }
747              
748              
749             =item coderef_blessed
750              
751             # Code
752             bless sub {
753             my (%args) = @_;
754             return $args{x} - $args{y};
755             }, "I::Am::Code"
756              
757              
758             # YAML
759             --- !perl/code:I::Am::Code |-
760             {
761             use warnings;
762             use strict;
763             (my(%args) = @_);
764             (return ($args{'x'} - $args{'y'}));
765             }
766              
767              
768             =item hash
769              
770             # Code
771             {
772             U => 2,
773             B => 52,
774             }
775              
776              
777             # YAML
778             ---
779             B: 52
780             U: 2
781              
782              
783             =item hash_blessed
784              
785             # Code
786             bless {
787             U => 2,
788             B => 52,
789             }, 'A::Very::Exclusive::Class'
790              
791              
792             # YAML
793             --- !perl/hash:A::Very::Exclusive::Class
794             B: 52
795             U: 2
796              
797              
798             =item refref
799              
800             # Code
801             my $ref = { a => 'hash' };
802             my $refref = \$ref;
803             $refref;
804              
805              
806             # YAML
807             --- !perl/ref
808             =:
809             a: hash
810              
811              
812             =item refref_blessed
813              
814             # Code
815             my $ref = { a => 'hash' };
816             my $refref = bless \$ref, 'Foo';
817             $refref;
818              
819              
820             # YAML
821             --- !perl/ref:Foo
822             =:
823             a: hash
824              
825              
826             =item regexp
827              
828             # Code
829             my $string = 'unblessed';
830             qr{$string}
831              
832              
833             # YAML
834             --- !perl/regexp unblessed
835              
836              
837             =item regexp_blessed
838              
839             # Code
840             my $string = 'blessed';
841             bless qr{$string}, "Foo"
842              
843              
844             # YAML
845             --- !perl/regexp:Foo blessed
846              
847              
848             =item scalarref
849              
850             # Code
851             my $scalar = "some string";
852             my $scalarref = \$scalar;
853             $scalarref;
854              
855              
856             # YAML
857             --- !perl/scalar
858             =: some string
859              
860              
861             =item scalarref_blessed
862              
863             # Code
864             my $scalar = "some other string";
865             my $scalarref = bless \$scalar, 'Foo';
866             $scalarref;
867              
868              
869             # YAML
870             --- !perl/scalar:Foo
871             =: some other string
872              
873              
874              
875              
876             =back
877              
878             =cut
879              
880             ### END EXAMPLE
881              
882             =head2 METHODS
883              
884             =over
885              
886             =item new
887              
888             my $perl = YAML::PP::Schema::Perl->new(
889             tags => "!perl",
890             classes => ['MyClass'],
891             loadcode => 1,
892             dumpcode => 1,
893             );
894              
895             The constructor recognizes the following options:
896              
897             =over
898              
899             =item tags
900              
901             Default: 'C<!perl>'
902              
903             See L<"Tag Styles">
904              
905             =item classes
906              
907             Default: C<undef>
908              
909             Since: v0.017
910              
911             Accepts an array ref of class names
912              
913             =item loadcode
914              
915             Default: 0
916              
917             =item dumpcode
918              
919             Default: 1
920              
921             my $yp = YAML::PP->new( schema => [qw/ + Perl -dumpcode /] );
922              
923             =back
924              
925             =item register
926              
927             A class method called by L<YAML::PP::Schema>
928              
929             =item construct_ref, represent_ref
930              
931             Perl variables of the type C<REF> are represented in yaml like this:
932              
933             --- !perl/ref
934             =:
935             a: 1
936              
937             C<construct_ref> returns the perl data:
938              
939             my $data = YAML::PP::Schema::Perl->construct_ref([ '=', { some => 'data' } );
940             my $data = \{ a => 1 };
941              
942             C<represent_ref> turns a C<REF> variable into a YAML mapping:
943              
944             my $data = YAML::PP::Schema::Perl->represent_ref(\{ a => 1 });
945             my $data = { '=' => { a => 1 } };
946              
947             =item construct_scalar, represent_scalar
948              
949             Perl variables of the type C<SCALAR> are represented in yaml like this:
950              
951             --- !perl/scalar
952             =: string
953              
954             C<construct_scalar> returns the perl data:
955              
956             my $data = YAML::PP::Schema::Perl->construct_ref([ '=', 'string' );
957             my $data = \'string';
958              
959             C<represent_scalar> turns a C<SCALAR> variable into a YAML mapping:
960              
961             my $data = YAML::PP::Schema::Perl->represent_scalar(\'string');
962             my $data = { '=' => 'string' };
963              
964             =item construct_regex, represent_regex
965              
966             C<construct_regex> returns a C<qr{}> object from the YAML string:
967              
968             my $qr = YAML::PP::Schema::Perl->construct_regex('foo.*');
969              
970             C<represent_regex> returns a string representing the regex object:
971              
972             my $string = YAML::PP::Schema::Perl->represent_regex(qr{...});
973              
974             =item evaluate_code, represent_code
975              
976             C<evaluate_code> returns a code reference from a string. The string must
977             start with a C<{> and end with a C<}>.
978              
979             my $code = YAML::PP::Schema::Perl->evaluate_code('{ return 23 }');
980              
981             C<represent_code> returns a string representation of the code reference
982             with the help of B::Deparse:
983              
984             my $string = YAML::PP::Schema::Perl->represent_code(sub { return 23 });
985              
986             =item construct_glob, represent_glob
987              
988             C<construct_glob> returns a glob from a hash.
989              
990             my $glob = YAML::PP::Schema::Perl->construct_glob($hash);
991              
992             C<represent_glob> returns a hash representation of the glob.
993              
994             my $hash = YAML::PP::Schema::Perl->represent_glob($glob);
995              
996             =item object
997              
998             Does the same as C<bless>:
999              
1000             my $object = YAML::PP::Schema::Perl->object($data, $class);
1001              
1002             =back
1003              
1004             =cut