def test_const_set_size__string_ascii(): """Passing `const` will set the size of a string correctly for single byte encodings. """ field = fields.String(const="asdfghjkl") assert field.size is not None, "Size wasn't set." assert field.size == 9, "Size is incorrect."
def test_const_set_size__string_utf16(): """Passing `const` will set the size of a string correctly for multi-byte encodings. """ field = fields.String(const="asdf", encoding="utf-16-le") assert field.size is not None, "Size wasn't set." assert field.size == 8, "Size is incorrect."
class FAT12BootSector(binobj.Struct): jump = fields.Bytes(const=b"\xeb\x3c\x90") oem_name = fields.String(size=8, default="mkdosfs", pad_byte=b" ", encoding="ascii") bytes_per_sector = fields.UInt16(default=512) sectors_per_cluster = fields.UInt8() reserved_sectors = fields.UInt16(default=1) num_fats = fields.UInt8(default=2) max_root_entries = fields.UInt16(default=240) total_logical_sectors_16 = fields.UInt16() media_descriptor = fields.UInt8() sectors_per_fat = fields.UInt16() sectors_per_track = fields.UInt16() num_heads = fields.UInt16() num_hidden_sectors = fields.UInt32(default=0) total_logical_sectors_32 = fields.UInt32() drive_number = fields.UInt8() _reserved = fields.Bytes(const=b"\0", discard=True) _ex_boot_signature = fields.Bytes(const=b"\x29", discard=True) volume_id = fields.UInt32(default=lambda: random.randrange(2**32)) volume_label = fields.String(size=11) fs_type = fields.String(size=8, default="FAT12", pad_byte=b" ", encoding="ascii") boot_code = fields.Bytes(size=448, default=b"\xcc" * 448) boot_signature = fields.Bytes(const=b"\x55\xaa") @property def total_logical_sectors(self): return self.total_logical_sectors_16 or self.total_logical_sectors_32 @total_logical_sectors.setter def total_logical_sectors(self, total_sectors): if total_sectors < 1 or total_sectors >= 2**32: raise ValueError("Total sectors must be in [1, 2^32). Got: %d" % total_sectors) if total_sectors < 65535: self.total_logical_sectors_16 = total_sectors self.total_logical_sectors_32 = 0 else: self.total_logical_sectors_16 = 0 self.total_logical_sectors_32 = total_sectors
def test_dump__null_with_default_and_field_ref(size_field): """Successfully dump the expected number of nulls if the field is of variable length but has a defined size.""" value_field = fields.String(name="string", size=size_field, null_value=DEFAULT) assert value_field.allow_null is True serialized_value = value_field.to_bytes(None, all_fields={"size": 5}) assert serialized_value == b"\x00" * 5
class BasicClass(binobj.Struct): some_value: fields.UInt16 string: fields.String(size=16, encoding="ibm500") # noqa:F821 other_string: fields.StringZ = "Default Value"
def test_field_validator__dump_fails__one_func_passed(): field = fields.String(size=5, validate=alnum_validator) with pytest.raises(errors.ValidationError): field.to_bytes("ab!de")
class _Crash(binobj.Struct): n_numbers = fields.UInt8() numbers = fields.Array(fields.UInt8(), count="eof") eof = fields.String(const="ABC")
class BasicStructWithArraySizeFieldAsName(binobj.Struct): n_numbers = fields.UInt8() numbers = fields.Array(fields.UInt8(), count="n_numbers") eof = fields.String(const="ABC")
class BasicStructWithDefaults(binobj.Struct): string = fields.String(size=7) int64 = fields.Int64(endian="big", default=0) uint24 = fields.UnsignedInteger(size=3, endian="little")
def test_string__load_null_default(): field = fields.String(size=7, null_value=DEFAULT) assert field.from_bytes(b"\x00" * 7) is None
def test_loads__field_insufficient_data(): """Load a field when there's insufficient data -> BOOM""" with pytest.raises(errors.UnexpectedEOFError): fields.String(size=17).from_bytes(b"abc")
class _Dumb(binobj.Struct): first = fields.String(size=2) reserved = fields.Bytes(const=b"\0\0", discard=True) last = fields.String(size=2)
class _Crash(BasicStruct): string = fields.String(size=7)
class NestedConstArrayStruct(binobj.Struct): field_1 = fields.String(size=16) field_2 = fields.Array(fields.Nested(ConstArrayStruct), count=4)
class Basic(binobj.Struct): abc = fields.Bytes(const=b"ABC") ghi = fields.Int32() jkl = fields.Int64(default=0xBADC0FFEE) mno = fields.String(size=2)
class SubStruct(binobj.Struct): first = fields.UInt64(endian="big") second = fields.String(size=7)
def test_loads__no_size_crashes(): field = fields.String() with pytest.raises(errors.UndefinedSizeError): field.from_bytes(b"123")
class BasicStructWithArray(binobj.Struct): header = fields.String(const="ABC") numbers = fields.Array(fields.UInt16(endian="big"), count=2) trailer = fields.String(const="XYZ")
def test_string__dump_null_default(): field = fields.String(size=7, null_value=DEFAULT) assert field.to_bytes(None) == b"\x00" * 7
class BasicStructWithSentinelArray(binobj.Struct): numbers = fields.Array(fields.UInt8(), halt_check=bswsa_should_halt) eof = fields.String(const="ABC")
def test_string__null_value(null_value): field = fields.String(size=8, null_value=null_value, encoding="utf-16-le") assert field.from_bytes(b"N\x00U\x00L\x00L\x00") is None
class BasicStruct(binobj.Struct): """A basic structure.""" string = fields.String(size=7) int64 = fields.Int64(endian="big") uint24 = fields.UnsignedInteger(size=3, endian="little")