Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

abs_offset and adjust_offset not playing nicely #53

Closed
aidansteele opened this issue Jan 17, 2015 · 3 comments
Closed

abs_offset and adjust_offset not playing nicely #53

aidansteele opened this issue Jan 17, 2015 · 3 comments

Comments

@aidansteele
Copy link

Hi,

Love the library. I've been playing with the :adjust_offset option and ran into an issue. The issue may be with my understanding or the code. :) I'll demonstrate with an example

require 'bindata'
io = ["6B7963680001000000000010000000140000000000006A640000000B"].pack "H*"

class KeychainFile < BinData::Record
  endian :big
  string :magic, length: 4, asserted_value: 'kych'
  string :padding, read_length: 8
  uint32 :schema_offset # in this example, the value is 20
  uint32 :table_count, adjust_offset: lambda { schema_offset + 4 }
end

kf = KeychainFile.read io
kf.schema_offset.abs_offset # is 12, as expected
kf.table_count.abs_offset # is 16, where i would expect 24

It appears that abs_offset does not take into account the value returned by adjust_offset. The value of kf.table_count is located at offset 24 and my understanding of abs_offset is that it returns the location within the IO that houses the data. Is this a correct understanding? If so, I think there may be a bug but I am not clever enough to fix it :)

@aidansteele
Copy link
Author

I banged away at my keyboard and eventually ended up with this:

module BinData
  class Base
    def real_abs_offset
      if @params[:adjust_offset].nil?
        parent.real_abs_offset + parent.offset_of(self)
      else
        @lazy.lazy_eval @params[:adjust_offset]
      end
    end
  end
end

I can't really explain how/why it works (and I feel like a monkey at a typewriter) or it's terribly wrong, but it's allowed me to continue on with my current task. I thought it would be worth posting here to see your thoughts on it.

@dmendel
Copy link
Owner

dmendel commented Jan 17, 2015

:adjust_offset is an experimental feature (which is why it is undocumented see #52). I'm still working out how to achieve seeking fuctionality in a structured way. :adjust_offset, as it currently stands, is analogous to using goto to achieve looping.

:adjust_offset will eventually be replaced with a better solution. Your above monkey patch looks like a good fix to your problem.

Do be aware that :adjust_offset is only in effect when reading. It will not automatically do any seeking when writing.

@dmendel dmendel closed this as completed Jan 17, 2015
@dmendel
Copy link
Owner

dmendel commented Mar 4, 2016

BinData::Skip now has the :to_abs_offset option. This is the official way to perform seeking in a stream. Skip will ensure that #abs_offset is calculated correctly.

:adjust_offset remains for backwards compatibility.

Your example can be written as:

class KeychainFile < BinData::Record
  endian :big
  string :magic, length: 4, asserted_value: 'kych'
  string :padding, read_length: 8
  uint32 :schema_offset # in this example, the value is 20
  skip   to_abs_offset: lambda { schema_offset + 4 }
  uint32 :table_count
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants