-
Notifications
You must be signed in to change notification settings - Fork 83
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
(MODULES-2409) Endian-ness incorrect for DWORD and QWORD #95
(MODULES-2409) Endian-ness incorrect for DWORD and QWORD #95
Conversation
@joshcooper if you want to take a look this should be good. |
when Win32::Registry::REG_QWORD | ||
bytes = to_byte_array(data, FFI::Type::UINT64.size) | ||
# Q is 64-bit unsigned native (little) endian order | ||
bytes = [data].pack('Q').unpack('C*') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
irb(main):007:0> [0x12345678].pack('L').unpack('C*').map {|ch| ch.to_s(16)}
=> ["78", "56", "34", "12"]
irb(main):008:0> [0x1234567890ABCDEF].pack('Q').unpack('C*').map {|ch| ch.to_s(16)}
=> ["ef", "cd", "ab", "90", "78", "56", "34", "12"]
👍
- In 0b99718 a helper method to_byte_array was introduced to convert a numeric value into a properly padded byte array. Unfortunately that introduced an error as the byte array ordering was incorrect. This has caused DWORD and QWORD values to be written wrong. For instance, creating a native (little) endian string from a large 32-bit value (4294967294) should yield the following bytes: pry(main)> [2**32-2].pack('L').unpack('C*') => [254, 255, 255, 255] That can be further round-tripped with .pack('C*').unpack('L*')[0] However, using to_bytes_array, the bytes come back improperly ordered pry(main)> to_byte_array(2**32-2, 4) => [255, 255, 255, 254] pry(main)> [255, 255, 255, 254].pack('C*').unpack('L*')[0] => 4278190079 As a result, because of the improper ordering of bytes, the wrong value is written. - Previous tests were passing since the range of written values tested was below 0xFF (255). The first point at which written values diverge is 256, where the byte array [0, 1, 0, 0] should have been created, but instead [1, 0, 0, 0] was written. Therefore, new tests have been added to test writing DWORD and QWORD values at each byte boundary + 1 bit - for instance 0xFF + 1, 0xFFFF + 1, ad nauseum. - The simplest additional test to perform was to validate that the written values from the deletion test match what is expected. These values are randomly generated.
- Add an additional check to ensure that the registry 'write' method is never called, which can trigger Ruby's bad behavior.
da3bd6e
to
c022d8c
Compare
@joshcooper added some additional tests that verify round-trips. With the previous code, they all fail:
I think this is ready to go now. |
@@ -30,6 +30,9 @@ | |||
# also, expect that we're not using Rubys each_key / each_value which exhibit bad behavior | |||
Win32::Registry.any_instance.expects(:each_key).never | |||
Win32::Registry.any_instance.expects(:each_value).never | |||
|
|||
# this covers []= write_s write_i and write_bin | |||
Win32::Registry.any_instance.expects(:write).never |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
👍 |
Looks good. Merging. |
…-qword-endianess-wrong (MODULES-2409) Endian-ness incorrect for DWORD and QWORD
In 0b99718 a helper method to_byte_array was introduced to convert
a numeric value into a properly padded byte array. Unfortunately
that introduced an error as the byte array ordering was incorrect.
This has caused DWORD and QWORD values to be written wrong.
For instance, creating a native (little) endian string from a large
32-bit value (4294967294) should yield the following bytes:
pry(main)> [2*32-2].pack('L').unpack('C')
=> [254, 255, 255, 255]
That can be further round-tripped with .pack('C_').unpack('L_')[0]
However, using to_bytes_array, the bytes come back improperly ordered
pry(main)> to_byte_array(2**32-2, 4)
=> [255, 255, 255, 254]
pry(main)> [255, 255, 255, 254].pack('C_').unpack('L_')[0]
=> 4278190079
As a result, because of the improper ordering of bytes, the wrong
value is written.
Previous tests were passing since the range of written values
tested was below 0xFF (255). The first point at which written
values diverge is 256, where the byte array [0, 1, 0, 0] should
have been created, but instead [1, 0, 0, 0] was written.
The simplest additional test to perform was to validate that the
written values from the deletion test match what is expected.