psych 3.0.3.pre3-java → 3.2.1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@
3
3
  #endif
4
4
 
5
5
  #if HAVE_CONFIG_H
6
- #include <config.h>
6
+ #include "config.h"
7
7
  #endif
8
8
 
9
9
  #include <yaml.h>
@@ -12,16 +12,6 @@
12
12
  #include <limits.h>
13
13
  #include <stddef.h>
14
14
 
15
- #ifndef _MSC_VER
16
- #include <stdint.h>
17
- #else
18
- #ifdef _WIN64
19
- #define PTRDIFF_MAX _I64_MAX
20
- #else
21
- #define PTRDIFF_MAX INT_MAX
22
- #endif
23
- #endif
24
-
25
15
  /*
26
16
  * Memory management.
27
17
  */
@@ -80,6 +70,17 @@ yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
80
70
 
81
71
  #define OUTPUT_RAW_BUFFER_SIZE (OUTPUT_BUFFER_SIZE*2+2)
82
72
 
73
+ /*
74
+ * The maximum size of a YAML input file.
75
+ * This used to be PTRDIFF_MAX, but that's not entirely portable
76
+ * because stdint.h isn't available on all platforms.
77
+ * It is not entirely clear why this isn't the maximum value
78
+ * that can fit into the parser->offset field.
79
+ */
80
+
81
+ #define MAX_FILE_SIZE (~(size_t)0 / 2)
82
+
83
+
83
84
  /*
84
85
  * The size of other stacks and queues.
85
86
  */
@@ -93,7 +94,7 @@ yaml_parser_fetch_more_tokens(yaml_parser_t *parser);
93
94
  */
94
95
 
95
96
  #define BUFFER_INIT(context,buffer,size) \
96
- (((buffer).start = yaml_malloc(size)) ? \
97
+ (((buffer).start = (yaml_char_t *)yaml_malloc(size)) ? \
97
98
  ((buffer).last = (buffer).pointer = (buffer).start, \
98
99
  (buffer).end = (buffer).start+(size), \
99
100
  1) : \
@@ -133,7 +134,7 @@ yaml_string_join(
133
134
  (value).pointer = (string))
134
135
 
135
136
  #define STRING_INIT(context,string,size) \
136
- (((string).start = yaml_malloc(size)) ? \
137
+ (((string).start = YAML_MALLOC(size)) ? \
137
138
  ((string).pointer = (string).start, \
138
139
  (string).end = (string).start+(size), \
139
140
  memset((string).start, 0, (size)), \
@@ -174,14 +175,14 @@ yaml_string_join(
174
175
  * Check the octet at the specified position.
175
176
  */
176
177
 
177
- #define CHECK_AT(string,octet,offset) \
178
+ #define CHECK_AT(string,octet,offset) \
178
179
  ((string).pointer[offset] == (yaml_char_t)(octet))
179
180
 
180
181
  /*
181
182
  * Check the current octet in the buffer.
182
183
  */
183
184
 
184
- #define CHECK(string,octet) CHECK_AT((string),(octet),0)
185
+ #define CHECK(string,octet) (CHECK_AT((string),(octet),0))
185
186
 
186
187
  /*
187
188
  * Check if the character at the specified position is an alphabetical
@@ -423,10 +424,10 @@ yaml_stack_extend(void **start, void **top, void **end);
423
424
  YAML_DECLARE(int)
424
425
  yaml_queue_extend(void **start, void **head, void **tail, void **end);
425
426
 
426
- #define STACK_INIT(context,stack,size) \
427
- (((stack).start = yaml_malloc((size)*sizeof(*(stack).start))) ? \
427
+ #define STACK_INIT(context,stack,type) \
428
+ (((stack).start = (type)yaml_malloc(INITIAL_STACK_SIZE*sizeof(*(stack).start))) ? \
428
429
  ((stack).top = (stack).start, \
429
- (stack).end = (stack).start+(size), \
430
+ (stack).end = (stack).start+INITIAL_STACK_SIZE, \
430
431
  1) : \
431
432
  ((context)->error = YAML_MEMORY_ERROR, \
432
433
  0))
@@ -456,8 +457,8 @@ yaml_queue_extend(void **start, void **head, void **tail, void **end);
456
457
  #define POP(context,stack) \
457
458
  (*(--(stack).top))
458
459
 
459
- #define QUEUE_INIT(context,queue,size) \
460
- (((queue).start = yaml_malloc((size)*sizeof(*(queue).start))) ? \
460
+ #define QUEUE_INIT(context,queue,size,type) \
461
+ (((queue).start = (type)yaml_malloc((size)*sizeof(*(queue).start))) ? \
461
462
  ((queue).head = (queue).tail = (queue).start, \
462
463
  (queue).end = (queue).start+(size), \
463
464
  1) : \
@@ -660,3 +661,28 @@ yaml_queue_extend(void **start, void **head, void **tail, void **end);
660
661
  (node).data.mapping.pairs.end = (node_pairs_end), \
661
662
  (node).data.mapping.pairs.top = (node_pairs_start), \
662
663
  (node).data.mapping.style = (node_style))
664
+
665
+ /* Strict C compiler warning helpers */
666
+
667
+ #if defined(__clang__) || defined(__GNUC__)
668
+ # define HASATTRIBUTE_UNUSED
669
+ #endif
670
+ #ifdef HASATTRIBUTE_UNUSED
671
+ # define __attribute__unused__ __attribute__((__unused__))
672
+ #else
673
+ # define __attribute__unused__
674
+ #endif
675
+
676
+ /* Shim arguments are arguments that must be included in your function,
677
+ * but serve no purpose inside. Silence compiler warnings. */
678
+ #define SHIM(a) /*@unused@*/ a __attribute__unused__
679
+
680
+ /* UNUSED_PARAM() marks a shim argument in the body to silence compiler warnings */
681
+ #ifdef __clang__
682
+ # define UNUSED_PARAM(a) (void)(a);
683
+ #else
684
+ # define UNUSED_PARAM(a) /*@-noeffect*/if (0) (void)(a)/*@=noeffect*/;
685
+ #endif
686
+
687
+ #define YAML_MALLOC_STATIC(type) (type*)yaml_malloc(sizeof(type))
688
+ #define YAML_MALLOC(size) (yaml_char_t *)yaml_malloc(size)
@@ -10,11 +10,7 @@ when 'jruby'
10
10
  org.jruby.ext.psych.PsychLibrary.new.load(JRuby.runtime, false)
11
11
  end
12
12
  else
13
- begin
14
- require "#{RUBY_VERSION[/\d+\.\d+/]}/psych.so"
15
- rescue LoadError
16
- require 'psych.so'
17
- end
13
+ require 'psych.so'
18
14
  end
19
15
  require 'psych/nodes'
20
16
  require 'psych/streaming'
@@ -36,7 +32,7 @@ require 'psych/class_loader'
36
32
  # = Overview
37
33
  #
38
34
  # Psych is a YAML parser and emitter.
39
- # Psych leverages libyaml [Home page: http://pyyaml.org/wiki/LibYAML]
35
+ # Psych leverages libyaml [Home page: https://pyyaml.org/wiki/LibYAML]
40
36
  # or [HG repo: https://bitbucket.org/xi/libyaml] for its YAML parsing
41
37
  # and emitting capabilities. In addition to wrapping libyaml, Psych also
42
38
  # knows how to serialize and de-serialize most Ruby objects to and from
@@ -78,12 +74,15 @@ require 'psych/class_loader'
78
74
  #
79
75
  # ==== Reading from a string
80
76
  #
81
- # Psych.load("--- a") # => 'a'
82
- # Psych.load("---\n - a\n - b") # => ['a', 'b']
77
+ # Psych.safe_load("--- a") # => 'a'
78
+ # Psych.safe_load("---\n - a\n - b") # => ['a', 'b']
79
+ # # From a trusted string:
80
+ # Psych.load("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") # => 0..42
83
81
  #
84
82
  # ==== Reading from a file
85
83
  #
86
- # Psych.load_file("database.yml")
84
+ # Psych.safe_load_file("data.yml", permitted_classes: [Date])
85
+ # Psych.load_file("trusted_database.yml")
87
86
  #
88
87
  # ==== Exception handling
89
88
  #
@@ -235,14 +234,16 @@ require 'psych/class_loader'
235
234
  module Psych
236
235
  # The version of libyaml Psych is using
237
236
  LIBYAML_VERSION = Psych.libyaml_version.join '.'
238
-
239
- FALLBACK = Struct.new :to_ruby # :nodoc:
237
+ # Deprecation guard
238
+ NOT_GIVEN = Object.new
239
+ private_constant :NOT_GIVEN
240
240
 
241
241
  ###
242
242
  # Load +yaml+ in to a Ruby data structure. If multiple documents are
243
243
  # provided, the object contained in the first document will be returned.
244
- # +filename+ will be used in the exception message if any exception is raised
245
- # while parsing.
244
+ # +filename+ will be used in the exception message if any exception
245
+ # is raised while parsing. If +yaml+ is empty, it returns
246
+ # the specified +fallback+ return value, which defaults to +false+.
246
247
  #
247
248
  # Raises a Psych::SyntaxError when a YAML syntax error is detected.
248
249
  #
@@ -252,7 +253,7 @@ module Psych
252
253
  # Psych.load("---\n - a\n - b") # => ['a', 'b']
253
254
  #
254
255
  # begin
255
- # Psych.load("--- `", "file.txt")
256
+ # Psych.load("--- `", filename: "file.txt")
256
257
  # rescue Psych::SyntaxError => ex
257
258
  # ex.file # => 'file.txt'
258
259
  # ex.message # => "(file.txt): found character that cannot start any token"
@@ -264,11 +265,21 @@ module Psych
264
265
  # Psych.load("---\n foo: bar") # => {"foo"=>"bar"}
265
266
  # Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
266
267
  #
267
- def self.load yaml, filename = nil, fallback: false, symbolize_names: false
268
- result = parse(yaml, filename, fallback: fallback)
269
- result = result.to_ruby if result
270
- symbolize_names!(result) if symbolize_names
271
- result
268
+ # Raises a TypeError when `yaml` parameter is NilClass
269
+ #
270
+ # NOTE: This method *should not* be used to parse untrusted documents, such as
271
+ # YAML documents that are supplied via user input. Instead, please use the
272
+ # safe_load method.
273
+ #
274
+ def self.load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, symbolize_names: false, freeze: false
275
+ if legacy_filename != NOT_GIVEN
276
+ warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load is deprecated. Use keyword argument like Psych.load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
277
+ filename = legacy_filename
278
+ end
279
+
280
+ result = parse(yaml, filename: filename)
281
+ return fallback unless result
282
+ result.to_ruby(symbolize_names: symbolize_names, freeze: freeze)
272
283
  end
273
284
 
274
285
  ###
@@ -284,27 +295,27 @@ module Psych
284
295
  # * Hash
285
296
  #
286
297
  # Recursive data structures are not allowed by default. Arbitrary classes
287
- # can be allowed by adding those classes to the +whitelist+. They are
298
+ # can be allowed by adding those classes to the +permitted_classes+ keyword argument. They are
288
299
  # additive. For example, to allow Date deserialization:
289
300
  #
290
- # Psych.safe_load(yaml, [Date])
301
+ # Psych.safe_load(yaml, permitted_classes: [Date])
291
302
  #
292
303
  # Now the Date class can be loaded in addition to the classes listed above.
293
304
  #
294
- # Aliases can be explicitly allowed by changing the +aliases+ parameter.
305
+ # Aliases can be explicitly allowed by changing the +aliases+ keyword argument.
295
306
  # For example:
296
307
  #
297
308
  # x = []
298
309
  # x << x
299
310
  # yaml = Psych.dump x
300
311
  # Psych.safe_load yaml # => raises an exception
301
- # Psych.safe_load yaml, [], [], true # => loads the aliases
312
+ # Psych.safe_load yaml, aliases: true # => loads the aliases
302
313
  #
303
314
  # A Psych::DisallowedClass exception will be raised if the yaml contains a
304
- # class that isn't in the whitelist.
315
+ # class that isn't in the +permitted_classes+ list.
305
316
  #
306
317
  # A Psych::BadAlias exception will be raised if the yaml contains aliases
307
- # but the +aliases+ parameter is set to false.
318
+ # but the +aliases+ keyword argument is set to false.
308
319
  #
309
320
  # +filename+ will be used in the exception message if any exception is raised
310
321
  # while parsing.
@@ -315,20 +326,39 @@ module Psych
315
326
  # Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
316
327
  # Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
317
328
  #
318
- def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil, symbolize_names: false
319
- result = parse(yaml, filename)
320
- return unless result
329
+ def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false
330
+ if legacy_permitted_classes != NOT_GIVEN
331
+ warn_with_uplevel 'Passing permitted_classes with the 2nd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_classes: ...) instead.', uplevel: 1 if $VERBOSE
332
+ permitted_classes = legacy_permitted_classes
333
+ end
321
334
 
322
- class_loader = ClassLoader::Restricted.new(whitelist_classes.map(&:to_s),
323
- whitelist_symbols.map(&:to_s))
324
- scanner = ScalarScanner.new class_loader
325
- if aliases
326
- visitor = Visitors::ToRuby.new scanner, class_loader
327
- else
328
- visitor = Visitors::NoAliasRuby.new scanner, class_loader
335
+ if legacy_permitted_symbols != NOT_GIVEN
336
+ warn_with_uplevel 'Passing permitted_symbols with the 3rd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_symbols: ...) instead.', uplevel: 1 if $VERBOSE
337
+ permitted_symbols = legacy_permitted_symbols
338
+ end
339
+
340
+ if legacy_aliases != NOT_GIVEN
341
+ warn_with_uplevel 'Passing aliases with the 4th argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, aliases: ...) instead.', uplevel: 1 if $VERBOSE
342
+ aliases = legacy_aliases
343
+ end
344
+
345
+ if legacy_filename != NOT_GIVEN
346
+ warn_with_uplevel 'Passing filename with the 5th argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
347
+ filename = legacy_filename
329
348
  end
349
+
350
+ result = parse(yaml, filename: filename)
351
+ return fallback unless result
352
+
353
+ class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s),
354
+ permitted_symbols.map(&:to_s))
355
+ scanner = ScalarScanner.new class_loader
356
+ visitor = if aliases
357
+ Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
358
+ else
359
+ Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
360
+ end
330
361
  result = visitor.accept result
331
- symbolize_names!(result) if symbolize_names
332
362
  result
333
363
  end
334
364
 
@@ -344,28 +374,40 @@ module Psych
344
374
  # Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Document:0x00>
345
375
  #
346
376
  # begin
347
- # Psych.parse("--- `", "file.txt")
377
+ # Psych.parse("--- `", filename: "file.txt")
348
378
  # rescue Psych::SyntaxError => ex
349
379
  # ex.file # => 'file.txt'
350
380
  # ex.message # => "(file.txt): found character that cannot start any token"
351
381
  # end
352
382
  #
353
383
  # See Psych::Nodes for more information about YAML AST.
354
- def self.parse yaml, filename = nil, fallback: false
355
- parse_stream(yaml, filename) do |node|
384
+ def self.parse yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: NOT_GIVEN
385
+ if legacy_filename != NOT_GIVEN
386
+ warn_with_uplevel 'Passing filename with the 2nd argument of Psych.parse is deprecated. Use keyword argument like Psych.parse(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
387
+ filename = legacy_filename
388
+ end
389
+
390
+ parse_stream(yaml, filename: filename) do |node|
356
391
  return node
357
392
  end
358
- fallback
393
+
394
+ if fallback != NOT_GIVEN
395
+ warn_with_uplevel 'Passing the `fallback` keyword argument of Psych.parse is deprecated.', uplevel: 1 if $VERBOSE
396
+ fallback
397
+ else
398
+ false
399
+ end
359
400
  end
360
401
 
361
402
  ###
362
403
  # Parse a file at +filename+. Returns the Psych::Nodes::Document.
363
404
  #
364
405
  # Raises a Psych::SyntaxError when a YAML syntax error is detected.
365
- def self.parse_file filename
366
- File.open filename, 'r:bom|utf-8' do |f|
367
- parse f, filename
406
+ def self.parse_file filename, fallback: false
407
+ result = File.open filename, 'r:bom|utf-8' do |f|
408
+ parse f, filename: filename
368
409
  end
410
+ result || fallback
369
411
  end
370
412
 
371
413
  ###
@@ -394,14 +436,21 @@ module Psych
394
436
  # end
395
437
  #
396
438
  # begin
397
- # Psych.parse_stream("--- `", "file.txt")
439
+ # Psych.parse_stream("--- `", filename: "file.txt")
398
440
  # rescue Psych::SyntaxError => ex
399
441
  # ex.file # => 'file.txt'
400
442
  # ex.message # => "(file.txt): found character that cannot start any token"
401
443
  # end
402
444
  #
445
+ # Raises a TypeError when NilClass is passed.
446
+ #
403
447
  # See Psych::Nodes for more information about YAML AST.
404
- def self.parse_stream yaml, filename = nil, &block
448
+ def self.parse_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, &block
449
+ if legacy_filename != NOT_GIVEN
450
+ warn_with_uplevel 'Passing filename with the 2nd argument of Psych.parse_stream is deprecated. Use keyword argument like Psych.parse_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
451
+ filename = legacy_filename
452
+ end
453
+
405
454
  if block_given?
406
455
  parser = Psych::Parser.new(Handlers::DocumentStream.new(&block))
407
456
  parser.parse yaml, filename
@@ -502,23 +551,46 @@ module Psych
502
551
  # end
503
552
  # list # => ['foo', 'bar']
504
553
  #
505
- def self.load_stream yaml, filename = nil
506
- if block_given?
507
- parse_stream(yaml, filename) do |node|
508
- yield node.to_ruby
509
- end
510
- else
511
- parse_stream(yaml, filename).children.map { |child| child.to_ruby }
554
+ def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: [], **kwargs
555
+ if legacy_filename != NOT_GIVEN
556
+ warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load_stream is deprecated. Use keyword argument like Psych.load_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
557
+ filename = legacy_filename
512
558
  end
559
+
560
+ result = if block_given?
561
+ parse_stream(yaml, filename: filename) do |node|
562
+ yield node.to_ruby(**kwargs)
563
+ end
564
+ else
565
+ parse_stream(yaml, filename: filename).children.map { |node| node.to_ruby(**kwargs) }
566
+ end
567
+
568
+ return fallback if result.is_a?(Array) && result.empty?
569
+ result
513
570
  end
514
571
 
515
572
  ###
516
573
  # Load the document contained in +filename+. Returns the yaml contained in
517
574
  # +filename+ as a Ruby object, or if the file is empty, it returns
518
575
  # the specified +fallback+ return value, which defaults to +false+.
519
- def self.load_file filename, fallback: false
576
+ #
577
+ # NOTE: This method *should not* be used to parse untrusted documents, such as
578
+ # YAML documents that are supplied via user input. Instead, please use the
579
+ # safe_load_file method.
580
+ def self.load_file filename, **kwargs
520
581
  File.open(filename, 'r:bom|utf-8') { |f|
521
- self.load f, filename, fallback: FALLBACK.new(fallback)
582
+ self.load f, filename: filename, **kwargs
583
+ }
584
+ end
585
+
586
+ ###
587
+ # Safely loads the document contained in +filename+. Returns the yaml contained in
588
+ # +filename+ as a Ruby object, or if the file is empty, it returns
589
+ # the specified +fallback+ return value, which defaults to +false+.
590
+ # See safe_load for options.
591
+ def self.safe_load_file filename, **kwargs
592
+ File.open(filename, 'r:bom|utf-8') { |f|
593
+ self.safe_load f, filename: filename, **kwargs
522
594
  }
523
595
  end
524
596
 
@@ -547,18 +619,20 @@ module Psych
547
619
  @dump_tags[klass] = tag
548
620
  end
549
621
 
550
- def self.symbolize_names!(result)
551
- case result
552
- when Hash
553
- result.keys.each do |key|
554
- result[key.to_sym] = symbolize_names!(result.delete(key))
555
- end
556
- when Array
557
- result.map! { |r| symbolize_names!(r) }
622
+ # Workaround for emulating `warn '...', uplevel: 1` in Ruby 2.4 or lower.
623
+ def self.warn_with_uplevel(message, uplevel: 1)
624
+ at = parse_caller(caller[uplevel]).join(':')
625
+ warn "#{at}: #{message}"
626
+ end
627
+
628
+ def self.parse_caller(at)
629
+ if /^(.+?):(\d+)(?::in `.*')?/ =~ at
630
+ file = $1
631
+ line = $2.to_i
632
+ [file, line]
558
633
  end
559
- result
560
634
  end
561
- private_class_method :symbolize_names!
635
+ private_class_method :warn_with_uplevel, :parse_caller
562
636
 
563
637
  class << self
564
638
  attr_accessor :load_tags