bindata 2.3.5 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bindata might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa6f6792c33e83b12b474d4e1b6a6b057fdd4425
4
- data.tar.gz: 347099da9214708c8799fef5e2aa1d8d6dc6a0bf
3
+ metadata.gz: 273d7545be91c481736500d0acc038741cce9327
4
+ data.tar.gz: 50326341e03e5bb741d78d7025470576e9389b34
5
5
  SHA512:
6
- metadata.gz: d9da79f0e12fdf4854db54801f3233b79ab5c3f30850e9d64bdcb27bcb7d937527a7e700d16fdf7abd2ebf9cd1caf1a72ef37488d989e1ead8406ba540327981
7
- data.tar.gz: a6f7fb484a15d030d277c723ba023f76308e4b87d36b73a28385de25705dc9776408323380eabbc087cd339b2738d2f0a5a3132ee0827c639c6cf150a7e9fe53
6
+ metadata.gz: ede91bae71b3e11e97d95e586fbaa215b4b3c09aa32cab067f9dfde861687c0a421c8b59654e5e4bd3661e5562b221010af71b3e5b66bcf5d3fcbc9a77003265
7
+ data.tar.gz: 043a8490cc4c132ff909562084e4e1b4de46bd1ae892f14e8b2c981a981052ada21eb3d2d3a615e381dd58a898e6f11ebf3b5095da010a083185cd2e0b19b77c
@@ -1,5 +1,10 @@
1
1
  = BinData Changelog
2
2
 
3
+ == Version 2.4.0 (2017-04-09)
4
+
5
+ * Reworked internal sanitizing API.
6
+ * Fix bit-based integers inside buffers. Reported by Claudius Coenen.
7
+
3
8
  == Version 2.3.5 (2017-01-19)
4
9
 
5
10
  * Enforce Integer#nbits > 0. Reported by Keenan Tims.
data/NEWS.rdoc CHANGED
@@ -1,3 +1,19 @@
1
+ = 2.4.0
2
+
3
+ This release changes the internal API for sanitizing parameters. This only
4
+ affects those that implement the `#sanitize_parameters` method.
5
+
6
+ = 2.3.x
7
+
8
+ if params.needs_sanitizing?(:type)
9
+ el_type, el_params = params[:type]
10
+ params[:type] = params.create_sanitized_object_prototype(el_type, el_params)
11
+ end
12
+
13
+ = 2.4.0
14
+
15
+ params.sanitize_object_prototype(:type)
16
+
1
17
  = 2.3.0
2
18
 
3
19
  This release adds I/O features.
@@ -275,9 +275,8 @@ module BinData
275
275
 
276
276
  class ArrayArgProcessor < BaseArgProcessor
277
277
  def sanitize_parameters!(obj_class, params) #:nodoc:
278
- unless params.has_parameter?(:initial_length) ||
279
- params.has_parameter?(:read_until)
280
- # ensure one of :initial_length and :read_until exists
278
+ # ensure one of :initial_length and :read_until exists
279
+ unless params.has_at_least_one_of?(:initial_length, :read_until)
281
280
  params[:initial_length] = 0
282
281
  end
283
282
 
@@ -286,11 +285,7 @@ module BinData
286
285
  params.must_be_integer(:initial_length)
287
286
 
288
287
  params.merge!(obj_class.dsl_params)
289
-
290
- if params.needs_sanitizing?(:type)
291
- el_type, el_params = params[:type]
292
- params[:type] = params.create_sanitized_object_prototype(el_type, el_params)
293
- end
288
+ params.sanitize_object_prototype(:type)
294
289
  end
295
290
  end
296
291
 
@@ -300,8 +295,7 @@ module BinData
300
295
  loop do
301
296
  element = append_new_element
302
297
  element.do_read(io)
303
- variables = { index: self.length - 1, element: self.last,
304
- array: self }
298
+ variables = { index: self.length - 1, element: self.last, array: self }
305
299
  break if eval_parameter(:read_until, variables)
306
300
  end
307
301
  end
@@ -73,12 +73,13 @@ module BinData
73
73
  raise ArgumentError, "can't set a nil value for #{debug_name}" if val.nil?
74
74
 
75
75
  raw_val = val.respond_to?(:snapshot) ? val.snapshot : val
76
- @value = begin
77
- raw_val.dup
78
- rescue TypeError
79
- # can't dup Fixnums
80
- raw_val
81
- end
76
+ @value =
77
+ begin
78
+ raw_val.dup
79
+ rescue TypeError
80
+ # can't dup Fixnums
81
+ raw_val
82
+ end
82
83
  end
83
84
 
84
85
  def snapshot
@@ -101,9 +102,10 @@ module BinData
101
102
  def method_missing(symbol, *args, &block) #:nodoc:
102
103
  child = snapshot
103
104
  if child.respond_to?(symbol)
104
- self.class.class_eval "def #{symbol}(*args, &block);" \
105
- " snapshot.#{symbol}(*args, &block);" \
106
- "end"
105
+ self.class.class_eval \
106
+ "def #{symbol}(*args, &block);" \
107
+ " snapshot.#{symbol}(*args, &block);" \
108
+ "end"
107
109
  child.__send__(symbol, *args, &block)
108
110
  else
109
111
  super
@@ -179,13 +181,14 @@ module BinData
179
181
  current_value = snapshot
180
182
  expected = eval_parameter(:assert, value: current_value)
181
183
 
182
- msg = if !expected
183
- "value '#{current_value}' not as expected"
184
- elsif expected != true && current_value != expected
185
- "value is '#{current_value}' but expected '#{expected}'"
186
- else
187
- nil
188
- end
184
+ msg =
185
+ if !expected
186
+ "value '#{current_value}' not as expected"
187
+ elsif expected != true && current_value != expected
188
+ "value is '#{current_value}' but expected '#{expected}'"
189
+ else
190
+ nil
191
+ end
189
192
 
190
193
  raise ValidityError, "#{msg} for #{debug_name}" if msg
191
194
  end
@@ -10,7 +10,8 @@ module BinData
10
10
  unless BinData.const_defined?(name)
11
11
  BinData.module_eval <<-END
12
12
  class #{name} < BinData::BasePrimitive
13
- BitField.define_methods(self, #{nbits.inspect}, #{endian.inspect}, #{signed.inspect})
13
+ # nbits is either an integer or the symbol `:nbits`
14
+ BitField.define_methods(self, #{nbits.inspect}, :#{endian}, :#{signed})
14
15
  end
15
16
  END
16
17
  end
@@ -110,13 +110,8 @@ module BinData
110
110
 
111
111
  def sanitize_parameters!(obj_class, params)
112
112
  params.merge!(obj_class.dsl_params)
113
-
114
113
  params.must_be_integer(:length)
115
-
116
- if params.needs_sanitizing?(:type)
117
- el_type, el_params = params[:type]
118
- params[:type] = params.create_sanitized_object_prototype(el_type, el_params)
119
- end
114
+ params.sanitize_object_prototype(:type)
120
115
  end
121
116
  end
122
117
  end
@@ -122,10 +122,10 @@ module BinData
122
122
  def sanitize_parameters!(obj_class, params) #:nodoc:
123
123
  params.merge!(obj_class.dsl_params)
124
124
 
125
- if params.needs_sanitizing?(:choices)
126
- choices = choices_as_hash(params[:choices])
127
- ensure_valid_keys(choices)
128
- params[:choices] = params.create_sanitized_choices(choices)
125
+ params.sanitize_choices(:choices) do |choices|
126
+ hash_choices = choices_as_hash(choices)
127
+ ensure_valid_keys(hash_choices)
128
+ hash_choices
129
129
  end
130
130
  end
131
131
 
@@ -141,13 +141,8 @@ module BinData
141
141
 
142
142
  def sanitize_parameters!(obj_class, params)
143
143
  params.merge!(obj_class.dsl_params)
144
-
145
144
  params.must_be_integer(:read_abs_offset)
146
-
147
- if params.needs_sanitizing?(:type)
148
- el_type, el_params = params[:type]
149
- params[:type] = params.create_sanitized_object_prototype(el_type, el_params)
150
- end
145
+ params.sanitize_object_prototype(:type)
151
146
  end
152
147
  end
153
148
 
@@ -157,10 +152,9 @@ module BinData
157
152
  # The +auto_call_delayed_io+ keyword sets a data object tree to perform
158
153
  # multi pass I/O automatically.
159
154
  def auto_call_delayed_io
160
- include AutoCallDelayedIO
161
-
162
155
  return if DelayedIO.method_defined? :initialize_instance_without_record_io
163
156
 
157
+ include AutoCallDelayedIO
164
158
  DelayedIO.send(:alias_method, :initialize_instance_without_record_io, :initialize_instance)
165
159
  DelayedIO.send(:define_method, :initialize_instance) do
166
160
  if @parent && !defined? @delayed_io_recorded
@@ -107,11 +107,7 @@ module BinData
107
107
  end
108
108
 
109
109
  def fields
110
- @fields ||= begin
111
- SanitizedFields.new(hints).tap do |san_fields|
112
- san_fields.copy_fields(parent_fields) if parent_fields
113
- end
114
- end
110
+ @fields ||= SanitizedFields.new(hints, parent_fields)
115
111
  end
116
112
 
117
113
  def dsl_params
@@ -273,11 +273,7 @@ module BinData
273
273
  # If the data read is too short an IOError is raised.
274
274
  def readbytes(n)
275
275
  reset_read_bits
276
-
277
- str = read(n)
278
- raise EOFError, "End of file reached" if str.nil?
279
- raise IOError, "data truncated" if str.size < n
280
- str
276
+ read(n)
281
277
  end
282
278
 
283
279
  # Reads all remaining bytes from the stream.
@@ -313,7 +309,12 @@ module BinData
313
309
  private
314
310
 
315
311
  def read(n = nil)
316
- read_raw(buffer_limited_n(n))
312
+ str = read_raw(buffer_limited_n(n))
313
+ if n
314
+ raise EOFError, "End of file reached" if str.nil?
315
+ raise IOError, "data truncated" if str.size < n
316
+ end
317
+ str
317
318
  end
318
319
 
319
320
  def read_big_endian_bits(nbits)
@@ -329,10 +330,7 @@ module BinData
329
330
  end
330
331
 
331
332
  def accumulate_big_endian_bits
332
- byte = read(1)
333
- raise EOFError, "End of file reached" if byte.nil?
334
- byte = byte.unpack('C').at(0) & 0xff
335
-
333
+ byte = read(1).unpack('C').at(0) & 0xff
336
334
  @rval = (@rval << 8) | byte
337
335
  @rnbits += 8
338
336
  end
@@ -350,10 +348,7 @@ module BinData
350
348
  end
351
349
 
352
350
  def accumulate_little_endian_bits
353
- byte = read(1)
354
- raise EOFError, "End of file reached" if byte.nil?
355
- byte = byte.unpack('C').at(0) & 0xff
356
-
351
+ byte = read(1).unpack('C').at(0) & 0xff
357
352
  @rval = @rval | (byte << @rnbits)
358
353
  @rnbits += 8
359
354
  end
@@ -43,11 +43,13 @@ module BinData
43
43
 
44
44
  # Convert CamelCase +name+ to underscore style.
45
45
  def underscore_name(name)
46
- name.to_s.sub(/.*::/, "").
47
- gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
48
- gsub(/([a-z\d])([A-Z])/, '\1_\2').
49
- tr("-", "_").
50
- downcase
46
+ name.
47
+ to_s.
48
+ sub(/.*::/, "").
49
+ gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
50
+ gsub(/([a-z\d])([A-Z])/, '\1_\2').
51
+ tr("-", "_").
52
+ downcase
51
53
  end
52
54
 
53
55
  #---------------
@@ -72,11 +72,14 @@ module BinData
72
72
  class SanitizedFields < SanitizedParameter
73
73
  include Enumerable
74
74
 
75
- def initialize(hints)
76
- @fields = []
77
- @hints = hints
75
+ def initialize(hints, base_fields = nil)
76
+ @hints = hints
77
+ if base_fields
78
+ @fields = base_fields.raw_fields
79
+ else
80
+ @fields = []
81
+ end
78
82
  end
79
- attr_reader :fields
80
83
 
81
84
  def add_field(type, name, params)
82
85
  name = nil if name == ""
@@ -84,6 +87,10 @@ module BinData
84
87
  @fields << SanitizedField.new(name, type, params, @hints)
85
88
  end
86
89
 
90
+ def raw_fields
91
+ @fields.dup
92
+ end
93
+
87
94
  def [](idx)
88
95
  @fields[idx]
89
96
  end
@@ -119,10 +126,6 @@ module BinData
119
126
  def any_field_has_parameter?(parameter)
120
127
  @fields.any? { |f| f.has_parameter?(parameter) }
121
128
  end
122
-
123
- def copy_fields(other)
124
- @fields.concat(other.fields)
125
- end
126
129
  end
127
130
  #----------------------------------------------------------------------------
128
131
 
@@ -209,10 +212,12 @@ module BinData
209
212
 
210
213
  alias_method :has_parameter?, :key?
211
214
 
212
- def needs_sanitizing?(key)
213
- parameter = self[key]
215
+ def has_at_least_one_of?(*keys)
216
+ keys.each do |key|
217
+ return true if has_parameter?(key)
218
+ end
214
219
 
215
- parameter && !parameter.is_a?(SanitizedParameter)
220
+ false
216
221
  end
217
222
 
218
223
  def warn_replacement_parameter(bad_key, suggested_key)
@@ -245,36 +250,46 @@ module BinData
245
250
  end
246
251
  end
247
252
 
248
- def hints
249
- { endian: self[:endian], search_prefix: self[:search_prefix] }
253
+ def rename_parameter(old_key, new_key)
254
+ if has_parameter?(old_key)
255
+ self[new_key] = delete(old_key)
256
+ end
250
257
  end
251
258
 
252
- def create_sanitized_endian(endian)
253
- if endian == :big
254
- BIG_ENDIAN
255
- elsif endian == :little
256
- LITTLE_ENDIAN
257
- elsif endian == :big_and_little
258
- raise ArgumentError, "endian: :big or endian: :little is required"
259
- else
260
- raise ArgumentError, "unknown value for endian '#{endian}'"
259
+ def sanitize_object_prototype(key)
260
+ sanitize(key) { |obj_type, obj_params| create_sanitized_object_prototype(obj_type, obj_params) }
261
+ end
262
+
263
+ def sanitize_fields(key, &block)
264
+ sanitize(key) do |fields|
265
+ sanitized_fields = create_sanitized_fields
266
+ yield(fields, sanitized_fields)
267
+ sanitized_fields
261
268
  end
262
269
  end
263
270
 
264
- def create_sanitized_params(params, the_class)
265
- SanitizedParameters.new(params, the_class, hints)
271
+ def sanitize_choices(key, &block)
272
+ sanitize(key) do |obj|
273
+ create_sanitized_choices(yield(obj))
274
+ end
266
275
  end
267
276
 
268
- def create_sanitized_choices(choices)
269
- SanitizedChoices.new(choices, hints)
277
+ def sanitize_endian(key)
278
+ sanitize(key) { |endian| create_sanitized_endian(endian) }
270
279
  end
271
280
 
272
- def create_sanitized_fields
273
- SanitizedFields.new(hints)
281
+ def sanitize(key, &block)
282
+ if needs_sanitizing?(key)
283
+ self[key] = yield(self[key])
284
+ end
274
285
  end
275
286
 
276
- def create_sanitized_object_prototype(obj_type, obj_params)
277
- SanitizedPrototype.new(obj_type, obj_params, hints)
287
+ def create_sanitized_params(params, the_class)
288
+ SanitizedParameters.new(params, the_class, hints)
289
+ end
290
+
291
+ def hints
292
+ { endian: self[:endian], search_prefix: self[:search_prefix] }
278
293
  end
279
294
 
280
295
  #---------------
@@ -290,6 +305,12 @@ module BinData
290
305
  ensure_mutual_exclusion_of_parameters
291
306
  end
292
307
 
308
+ def needs_sanitizing?(key)
309
+ parameter = self[key]
310
+
311
+ parameter && !parameter.is_a?(SanitizedParameter)
312
+ end
313
+
293
314
  def ensure_no_nil_values
294
315
  each do |key, value|
295
316
  if value.nil?
@@ -324,6 +345,30 @@ module BinData
324
345
  end
325
346
  end
326
347
  end
348
+
349
+ def create_sanitized_endian(endian)
350
+ if endian == :big
351
+ BIG_ENDIAN
352
+ elsif endian == :little
353
+ LITTLE_ENDIAN
354
+ elsif endian == :big_and_little
355
+ raise ArgumentError, "endian: :big or endian: :little is required"
356
+ else
357
+ raise ArgumentError, "unknown value for endian '#{endian}'"
358
+ end
359
+ end
360
+
361
+ def create_sanitized_choices(choices)
362
+ SanitizedChoices.new(choices, hints)
363
+ end
364
+
365
+ def create_sanitized_fields
366
+ SanitizedFields.new(hints)
367
+ end
368
+
369
+ def create_sanitized_object_prototype(obj_type, obj_params)
370
+ SanitizedPrototype.new(obj_type, obj_params, hints)
371
+ end
327
372
  end
328
373
  #----------------------------------------------------------------------------
329
374
  end
@@ -83,17 +83,12 @@ module BinData
83
83
 
84
84
  class SkipArgProcessor < BaseArgProcessor
85
85
  def sanitize_parameters!(obj_class, params)
86
- unless params.has_parameter?(:length) ||
87
- params.has_parameter?(:to_abs_offset) ||
88
- params.has_parameter?(:until_valid)
89
- raise ArgumentError, "#{obj_class} requires either :length, :to_abs_offset or :until_valid"
86
+ unless params.has_at_least_one_of?(:length, :to_abs_offset, :until_valid)
87
+ raise ArgumentError,
88
+ "#{obj_class} requires either :length, :to_abs_offset or :until_valid"
90
89
  end
91
90
  params.must_be_integer(:to_abs_offset, :length)
92
-
93
- if params.needs_sanitizing?(:until_valid)
94
- el_type, el_params = params[:until_valid]
95
- params[:until_valid] = params.create_sanitized_object_prototype(el_type, el_params)
96
- end
91
+ params.sanitize_object_prototype(:until_valid)
97
92
  end
98
93
  end
99
94
 
@@ -127,15 +127,8 @@ module BinData
127
127
  def sanitize_parameters!(obj_class, params)
128
128
  params.warn_replacement_parameter(:initial_length, :read_length)
129
129
  params.must_be_integer(:read_length, :length)
130
-
131
- if params.has_parameter?(:pad_left)
132
- params[:pad_front] = params.delete(:pad_left)
133
- end
134
-
135
- if params.has_parameter?(:pad_byte)
136
- byte = params[:pad_byte]
137
- params[:pad_byte] = sanitized_pad_byte(byte)
138
- end
130
+ params.rename_parameter(:pad_left, :pad_front)
131
+ params.sanitize(:pad_byte) { |byte| sanitized_pad_byte(byte) }
139
132
  end
140
133
 
141
134
  #-------------
@@ -62,19 +62,20 @@ module BinData
62
62
  optional_parameters :endian, :search_prefix, :hide
63
63
 
64
64
  # These reserved words may not be used as field names
65
- RESERVED = Hash[*
66
- (Hash.instance_methods +
67
- %w{alias and begin break case class def defined do else elsif
68
- end ensure false for if in module next nil not or redo
69
- rescue retry return self super then true undef unless until
70
- when while yield} +
71
- %w{array element index value} +
72
- %w{type initial_length read_until} +
73
- %w{fields endian search_prefix hide only_if byte_align} +
74
- %w{choices selection copy_on_change} +
75
- %w{read_abs_offset struct_params}).collect(&:to_sym).
76
- uniq.collect { |key| [key, true] }.flatten
77
- ]
65
+ RESERVED =
66
+ Hash[*
67
+ (Hash.instance_methods +
68
+ %w{alias and begin break case class def defined do else elsif
69
+ end ensure false for if in module next nil not or redo
70
+ rescue retry return self super then true undef unless until
71
+ when while yield} +
72
+ %w{array element index value} +
73
+ %w{type initial_length read_until} +
74
+ %w{fields endian search_prefix hide only_if byte_align} +
75
+ %w{choices selection copy_on_change} +
76
+ %w{read_abs_offset struct_params}).collect(&:to_sym).
77
+ uniq.collect { |key| [key, true] }.flatten
78
+ ]
78
79
 
79
80
  def initialize_shared_instance
80
81
  fields = get_parameter(:fields)
@@ -349,44 +350,38 @@ module BinData
349
350
  private
350
351
 
351
352
  def sanitize_endian(params)
352
- if params.needs_sanitizing?(:endian)
353
- endian = params.create_sanitized_endian(params[:endian])
354
- params[:endian] = endian
355
- end
353
+ params.sanitize_endian(:endian)
356
354
  end
357
355
 
358
356
  def sanitize_search_prefix(params)
359
- if params.needs_sanitizing?(:search_prefix)
357
+ params.sanitize(:search_prefix) do |sprefix|
360
358
  search_prefix = []
361
- Array(params[:search_prefix]).each do |prefix|
359
+ Array(sprefix).each do |prefix|
362
360
  prefix = prefix.to_s.chomp("_")
363
361
  search_prefix << prefix if prefix != ""
364
362
  end
365
363
 
366
- params[:search_prefix] = search_prefix
364
+ search_prefix
367
365
  end
368
366
  end
369
367
 
370
368
  def sanitize_fields(obj_class, params)
371
- if params.needs_sanitizing?(:fields)
372
- fields = params[:fields]
373
-
374
- params[:fields] = params.create_sanitized_fields
369
+ params.sanitize_fields(:fields) do |fields, sanitized_fields|
375
370
  fields.each do |ftype, fname, fparams|
376
- params[:fields].add_field(ftype, fname, fparams)
371
+ sanitized_fields.add_field(ftype, fname, fparams)
377
372
  end
378
373
 
379
- field_names = sanitized_field_names(params[:fields])
374
+ field_names = sanitized_field_names(sanitized_fields)
380
375
  ensure_field_names_are_valid(obj_class, field_names)
381
376
  end
382
377
  end
383
378
 
384
379
  def sanitize_hide(params)
385
- if params.needs_sanitizing?(:hide) && params.has_parameter?(:fields)
380
+ params.sanitize(:hide) do |hidden|
386
381
  field_names = sanitized_field_names(params[:fields])
387
- hfield_names = hidden_field_names(params[:hide])
382
+ hfield_names = hidden_field_names(hidden)
388
383
 
389
- params[:hide] = (hfield_names & field_names)
384
+ hfield_names & field_names
390
385
  end
391
386
  end
392
387
 
@@ -1,3 +1,3 @@
1
1
  module BinData
2
- VERSION = "2.3.5"
2
+ VERSION = "2.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bindata
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.5
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dion Mendel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-19 00:00:00.000000000 Z
11
+ date: 2017-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -163,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
163
163
  version: '0'
164
164
  requirements: []
165
165
  rubyforge_project: bindata
166
- rubygems_version: 2.4.5
166
+ rubygems_version: 2.6.8
167
167
  signing_key:
168
168
  specification_version: 4
169
169
  summary: A declarative way to read and write binary file formats