class ElementCountTests(CalculatedTestCase): __meta__ = False def setUp(self, cls=ElementCount): super(ElementCountTests, self).setUp(cls) self.length = 32 self.bit_field = BitField(value=0, length=self.length) def get_default_field(self, fuzzable=False, correction=None): return self.cls(self.depends_on_name, correction=correction, length=self.length, fuzzable=fuzzable, name=self.uut_name) def calculate(self, field): self.bit_field.set_current_value(len(field.get_rendered_fields())) return self.bit_field.render() def testContainerWithInternalContainer(self): container = Container( name=self.depends_on_name, fields=[ String('abc'), String('def'), Container( name='counts_as_one', fields=[ String('ghi'), String('jkl'), ]) ]) uut = self.get_default_field() full = Container([container, uut]) full.render() self.assertEqual(uut.render(), self.calculate(container)) del full def testInternalContainer(self): internal_container = Container( name=self.depends_on_name, fields=[ String('ghi', name='field3'), String('jkl', name='field4'), ]) container = Container( name='this_doesnt_count', fields=[ String('abc', name='field1'), String('def', name='field2'), internal_container ]) uut = self.get_default_field() full = Container([container, uut]) full.render() self.assertEqual(uut.render(), self.calculate(internal_container)) del full def testInvalidCorrectionStr(self): with self.assertRaises(KittyException): self.get_default_field(correction='boom')
class SizeTests(CalculatedTestCase): __meta__ = False def setUp(self, cls=Size, length=32): super(SizeTests, self).setUp(cls) self.bit_field = BitField(value=0, length=length) self.length = length def get_default_field(self, length=None, calc_func=None, fuzzable=False): if length is None: length = self.length if calc_func is None: return self.cls(self.depends_on_name, length=length, fuzzable=fuzzable) else: return self.cls(self.depends_on_name, length=length, calc_func=calc_func, fuzzable=fuzzable) def calculate(self, value, calc_func=None): if calc_func: val = calc_func(value) else: val = len(value.bytes) self.bit_field.set_current_value(val) return self.bit_field.render() def test_custom_func_valid(self): func = lambda x: len(x) original_field = self.get_original_field() calculated_field = self.get_default_field(calc_func=func) container = Container([original_field, calculated_field]) original_rendered = original_field.render() expected = self.calculate(original_rendered, calc_func=func) actual = calculated_field.render() self.assertEqual(expected, actual) while container.mutate(): original_rendered = original_field.render() expected = self.calculate(original_rendered, calc_func=func) actual = calculated_field.render() self.assertEqual(expected, actual) def test_custom_func_invalid_arguments(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=8, calc_func=lambda x, y: 1) def test_custom_func_invalid_return_type_str(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=8, calc_func=lambda x: "") def test_custom_func_invalid_return_type_bits(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=8, calc_func=lambda x: Bits()) def test_invalid_length_0(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=0) def test_invalid_length_negative(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=-3)
class ElementCountTests(CalculatedTestCase): __meta__ = False def setUp(self, cls=ElementCount): super(ElementCountTests, self).setUp(cls) self.length = 32 self.bit_field = BitField(value=0, length=self.length) def get_default_field(self, fuzzable=False, correction=None): return self.cls(self.depends_on_name, correction=correction, length=self.length, fuzzable=fuzzable, name=self.uut_name) def calculate(self, field): self.bit_field.set_current_value(len(field.get_rendered_fields())) return self.bit_field.render() def testContainerWithInternalContainer(self): container = Container(name=self.depends_on_name, fields=[ String('abc'), String('def'), Container(name='counts_as_one', fields=[ String('ghi'), String('jkl'), ]) ]) uut = self.get_default_field() full = Container([container, uut]) full.render() self.assertEqual(uut.render(), self.calculate(container)) del full def testInternalContainer(self): internal_container = Container(name=self.depends_on_name, fields=[ String('ghi', name='field3'), String('jkl', name='field4'), ]) container = Container(name='this_doesnt_count', fields=[ String('abc', name='field1'), String('def', name='field2'), internal_container ]) uut = self.get_default_field() full = Container([container, uut]) full.render() self.assertEqual(uut.render(), self.calculate(internal_container)) del full def testInvalidCorrectionStr(self): with self.assertRaises(KittyException): self.get_default_field(correction='boom')
class SizeTests(CalculatedTestCase): __meta__ = False def setUp(self, cls=Size, length=32): super(SizeTests, self).setUp(cls) self.bit_field = BitField(value=0, length=length) self.length = length def get_default_field(self, length=None, calc_func=None, fuzzable=False): if length is None: length = self.length if calc_func is None: return self.cls(self.depends_on_name, length=length, fuzzable=fuzzable, name='uut') else: return self.cls(self.depends_on_name, length=length, calc_func=calc_func, fuzzable=fuzzable, name='uut') def calculate(self, field, calc_func=None): value = field.render() if calc_func: val = calc_func(value) else: val = len(value.bytes) self.bit_field.set_current_value(val) return self.bit_field.render() def testCustomFuncValid(self): def func(x): return len(x) original_field = self.get_original_field() calculated_field = self.get_default_field(calc_func=func) container = Container([original_field, calculated_field]) expected = self.calculate(original_field, calc_func=func) actual = calculated_field.render() self.assertEqual(expected, actual) while container.mutate(): expected = self.calculate(original_field, calc_func=func) actual = calculated_field.render() self.assertEqual(expected, actual) def testInvalidLength0(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=0) def testInvalidLengthNegative(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=-3) def testSizeInclusiveAlone(self): self.length = 32 container = Container( name=self.depends_on_name, fields=[ self.get_default_field() ]) rendered = container.render() self.assertEqual(len(rendered), self.length) self.assertEquals(unpack('>I', rendered.tobytes())[0], self.length / 8)
class SizeTests(CalculatedTestCase): __meta__ = False def setUp(self, cls=Size, length=32): super(SizeTests, self).setUp(cls) self.bit_field = BitField(value=0, length=length) self.length = length def get_default_field(self, length=None, calc_func=None, fuzzable=False): if length is None: length = self.length if calc_func is None: return self.cls(self.depends_on_name, length=length, fuzzable=fuzzable, name=self.uut_name) else: return self.cls(self.depends_on_name, length=length, calc_func=calc_func, fuzzable=fuzzable, name=self.uut_name) def calculate(self, field, calc_func=None): value = field.render() if calc_func: val = calc_func(value) else: val = len(value.bytes) self.bit_field.set_current_value(val) return self.bit_field.render() def testCustomFuncValid(self): def func(x): return len(x) original_field = self.get_original_field() calculated_field = self.get_default_field(calc_func=func) container = Container([original_field, calculated_field]) expected = self.calculate(original_field, calc_func=func) actual = calculated_field.render() self.assertEqual(expected, actual) while container.mutate(): expected = self.calculate(original_field, calc_func=func) actual = calculated_field.render() self.assertEqual(expected, actual) def testInvalidLength0(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=0) def testInvalidLengthNegative(self): with self.assertRaises(KittyException): self.cls(self.depends_on_name, length=-3) def testSizeInclusiveAlone(self): self.length = 32 container = Container( name=self.depends_on_name, fields=[ self.get_default_field() ]) rendered = container.render() self.assertEqual(len(rendered), self.length) self.assertEquals(unpack('>I', rendered.tobytes())[0], self.length / 8)
class SizeInBytesTest(CalculatedTestCase): __meta__ = False def setUp(self, cls=SizeInBytes, length=32): super(SizeInBytesTest, self).setUp(cls) self.bit_field = BitField(value=0, length=length) self.length = length def get_default_field(self, fuzzable=False): return self.cls(self.depends_on_name, length=self.length, fuzzable=fuzzable) def calculate(self, value): self.bit_field.set_current_value(len(value.bytes)) return self.bit_field.render()
class SizeInBytesTest(CalculatedTestCase): __meta__ = False def setUp(self, cls=SizeInBytes, length=32): super(SizeInBytesTest, self).setUp(cls) self.bit_field = BitField(value=0, length=length) self.length = length def get_default_field(self, fuzzable=False): return self.cls(self.depends_on_name, length=self.length, fuzzable=fuzzable, name=self.uut_name) def calculate(self, field): value = field.render() self.bit_field.set_current_value(len(value.bytes)) return self.bit_field.render()
def testValueNegative(self): for full_range in [True, False]: self._base_check( BitField(value=-50, length=7, signed=True, full_range=full_range))
def testLengthTooSmallForValueUnsigned(self): for full_range in [True, False]: with self.assertRaises(KittyException): BitField(value=64, length=6, signed=False, full_range=full_range)
def _testIntsFromFile(self): values = ['0xffffffff', '-345345', '123', '0', '333', '56'] filename = './kitty_integers.txt' with open(filename, 'wb') as f: f.write('\n'.join(values)) self._base_check(BitField(name=self.uut_name, value=1, length=12)) os.remove(filename)
def testLengthTooSmallForMaxValue(self): for full_range in [True, False]: with self.assertRaises(KittyException): BitField(value=10, length=5, signed=True, max_value=17, full_range=full_range)
def GenerateHidReport(report_str, name=None): ''' Generate an HID report Container from a HID report string :param report_str: HID report string :param name: name of generated Container (default: None) :raises: KittyException if not enough bytes are left for command :examples: :: Template( name='MyHidReport', fields=GenerateHidReport( '05010906A101050719E029E7150025017501950881029501750881011900296515002565750895018100C0', ) ) ''' fields = [] index = 0 namer = NameGen() while index < len(report_str): opcode = report_str[index] num_args = opcode & 3 if index + num_args >= len(report_str): raise KittyException('Not enough bytes in hid report for last opcode') index += 1 cur_name = namer.gen(opcode) if num_args == 0: fields.append(UInt8(opcode, name=cur_name)) else: args = report_str[index:index + num_args] value = sum(args[i] << (i * 8) for i in range(len(args))) # little endian... fields.append(Container( name=cur_name, fields=[ UInt8(opcode, name='opcode'), BitField(value, 8 * len(args), encoder=ENC_INT_LE, name='value') ] )) index += num_args return OneOf( name=name, fields=[ Container( name='generation', fields=fields ), MutableField( name='mutation', value=report_str ), RandomHidReport( name='random_sequences' ), ])
def testLengthNonByteAlignedSigned(self): signed = True self._base_check(BitField(value=10, length=7, signed=signed)) self._base_check(BitField(value=10, length=14, signed=signed)) self._base_check(BitField(value=10, length=15, signed=signed)) self._base_check(BitField(value=10, length=16, signed=signed)) self._base_check(BitField(value=10, length=58, signed=signed)) self._base_check(BitField(value=10, length=111, signed=signed))
def testLengthNonByteAlignedSigned(self): signed = True for full_range in[True, False]: self._base_check(BitField(value=10, length=7, signed=signed, full_range=full_range)) self._base_check(BitField(value=10, length=14, signed=signed, full_range=full_range)) self._base_check(BitField(value=10, length=15, signed=signed)) self._base_check(BitField(value=10, length=16, signed=signed)) self._base_check(BitField(value=10, length=58, signed=signed)) self._base_check(BitField(value=10, length=111, signed=signed))
def __init__(self, name, tag, fields=None, tag_size=32, length_size=32, encoder=ENC_INT_BE, fuzzable=True, fuzz_tag=False, fuzz_length=True): ''' :param name: name of the tlv element :param tag: tag of element :param fields: element fields, e.g. value (default: None) :param tag_size: size of tag field in bits (default: 32) :param length_size: size of length field in bits (default: 32) :param encoder: encoder for tag and length fields (default: ENC_INT_BE) :param fuzzable: should fuzz the element (default: True) :param fuzz_tag: should fuzz the tag value (default: False) :param fuzz_length: should fuzz the element length (default: True) ''' tag_name = '%s-tag' % name len_name = '%s-length' % name val_name = '%s-value' % name if fields is None: fields = [] _fields = [ BitField(name=tag_name, value=tag, length=tag_size, signed=False, encoder=encoder, fuzzable=fuzz_tag), SizeInBytes(name=len_name, sized_field=val_name, length=length_size, encoder=encoder, fuzzable=fuzz_length), Container(name=val_name, fields=fields) ] super(TLV, self).__init__(fields=_fields, encoder=ENC_BITS_DEFAULT, fuzzable=fuzzable, name=name)
def __init__(self, value, num_bits=64, signed=False, fuzzable=True, name=None): ''' :param value: default integer value :param num_bits: number of bit in the integer (default: 64) :param signed: can the value be negative (default: False) :param fuzzable: should fuzz the container (default: True) :param name: name of container (default: None) ''' fields = [ BitField(name=_merge(name, 'int mutations'), value=value, length=num_bits, signed=signed, encoder=ENC_INT_DEC), String(name='string mutations', value='%s' % value) ] super(DecimalNumber, self).__init__(name=name, fields=fields, fuzzable=fuzzable)
def testValueNegative(self): self._base_check(BitField(value=-50, length=7, signed=True))
def testLengthVeryLarge(self): field = BitField(value=1, length=1) self._base_check(field)
name='Class-Specific interfaces', fields=[ SubDescriptor(name='cdc_header_functional_descriptor', descriptor_type=DescriptorType.cs_interface, fields=[ UInt8(name='bDesciptorSubType', value=FunctionalDescriptor.Header), LE16(name='bcdCDC', value=0x0101) ]), SubDescriptor(name='cdc_call_management_functional_descriptor', descriptor_type=DescriptorType.cs_interface, fields=[ UInt8(name='bDesciptorSubType', value=FunctionalDescriptor.CM), BitField(name='bmCapabilities', value=0, length=8), UInt8(name='bDataInterface', value=2) ]), SubDescriptor( name= 'cdc_abstract_control_management_functional_descriptor', descriptor_type=DescriptorType.cs_interface, fields=[ UInt8(name='bDesciptorSubType', value=FunctionalDescriptor.ACM), BitField(name='bmCapabilities', value=0, length=8) ]), SubDescriptor(name='cdc_union_functional_descriptor', descriptor_type=DescriptorType.cs_interface, fields=[
class IndexOfTestCase(CalculatedTestCase): __meta__ = False def setUp(self, cls=IndexOf): super(IndexOfTestCase, self).setUp(cls) self.length = 32 self.bit_field = BitField(value=0, length=self.length) def get_default_field(self, fuzzable=False): return self.cls(self.depends_on_name, length=self.length, fuzzable=fuzzable, name=self.uut_name) def calculate(self, field): rendered = field._enclosing.get_rendered_fields() if field in rendered: value = rendered.index(field) else: value = len(rendered) self.bit_field.set_current_value(value) return self.bit_field.render() def _testCorrectIndex(self, expected_index): field_list = [String('%d' % i) for i in range(20)] field_list[expected_index] = self.get_original_field() uut = self.get_default_field() t = Container(name='level1', fields=[uut, Container(name='level2', fields=field_list)]) rendered = uut.render().tobytes() result = unpack('>I', rendered)[0] self.assertEqual(result, expected_index) del t def testCorrectIndexFirst(self): self._testCorrectIndex(0) def testCorrectIndexMiddle(self): self._testCorrectIndex(10) def testCorrectIndexLast(self): self._testCorrectIndex(19) def testFieldNotRenderedAlone(self): expected_index = 0 uut = self.get_default_field() the_field = Static(name=self.depends_on_name, value='') t = Container(name='level1', fields=[uut, Container(name='level2', fields=the_field)]) rendered = uut.render().tobytes() result = unpack('>I', rendered)[0] self.assertEqual(result, expected_index) del t def testFieldNotRenderedWithOtherFields(self): expected_index = 3 uut = self.get_default_field() fields = [ Static(name=self.depends_on_name, value=''), Static('field1'), Static('field2'), Static('field3'), ] t = Container(name='level1', fields=[uut, Container(name='level2', fields=fields)]) rendered = uut.render().tobytes() result = unpack('>I', rendered)[0] self.assertEqual(result, expected_index) del t
def setUp(self, cls=IndexOf): super(IndexOfTestCase, self).setUp(cls) self.length = 32 self.bit_field = BitField(value=0, length=self.length)
def setUp(self, cls=SizeInBytes, length=32): super(SizeInBytesTest, self).setUp(cls) self.bit_field = BitField(value=0, length=length) self.length = length
def __init__(self, name, version=0x00, flags=0x0000000, fields=[], fuzzable=True): super(Mp4FullBox, self).__init__(name, fields=[ BE8(name="version", value=version), BitField(name="flags", value=flags, length=24, encoder=ENC_INT_BE), ] + fields, fuzzable=fuzzable)
def testLengthVerySmall(self): for full_range in[True, False]: self._base_check(BitField(value=1, length=1, full_range=full_range))
LE16(name='wFormatTag', value=0x0001) ]) # TODO: remove? audio_as_format_type_descriptor = Descriptor( name='audio_as_format_type_descriptor', descriptor_type=_DescriptorTypes.CS_INTERFACE, fields=[ UInt8(name='bDesciptorSubType', value=_AS_DescriptorSubTypes.FORMAT_TYPE), UInt8(name='bFormatType', value=0x01), UInt8(name='bNrChannels', value=0x01), UInt8(name='bSubFrameSize', value=0x02), UInt8(name='bBitResolution', value=0x10), UInt8(name='bSamFreqType', value=0x01), BitField(name='tSamFreq', length=24, value=0x01F40) ]) audio_hid_descriptor = Descriptor( name='audio_hid_descriptor', descriptor_type=_DescriptorTypes.HID, fields=[ DynamicInt('bcdHID', LE16(value=0x1001)), DynamicInt('bCountryCode', UInt8(value=0x00)), DynamicInt('bNumDescriptors', UInt8(value=0x01)), DynamicInt('bDescriptorType2', UInt8(value=_DescriptorTypes.HID_REPORT)), DynamicInt('wDescriptorLength', LE16(value=0x2b)), ]) # this descriptor is based on umap
def setUp(self, cls=ElementCount): super(ElementCountTests, self).setUp(cls) self.length = 32 self.bit_field = BitField(value=0, length=self.length)
def testLengthTooSmallForValueUnsigned(self): with self.assertRaises(KittyException): BitField(value=64, length=6, signed=False)
def testLengthTooSmallForMaxValue(self): with self.assertRaises(KittyException): BitField(value=10, length=5, signed=True, max_value=17)
def testLengthVeryLarge(self): for full_range in[True, False]: field = BitField(value=1, length=1) self._base_check(field)
class IndexOfTestCase(CalculatedTestCase): __meta__ = False def setUp(self, cls=IndexOf): super(IndexOfTestCase, self).setUp(cls) self.length = 32 self.bit_field = BitField(value=0, length=self.length) def get_default_field(self, fuzzable=False): return self.cls(self.depends_on_name, length=self.length, fuzzable=fuzzable, name='uut') def calculate(self, field): rendered = field._enclosing.get_rendered_fields() if field in rendered: value = rendered.index(field) else: value = len(rendered) self.bit_field.set_current_value(value) return self.bit_field.render() def _testCorrectIndex(self, expected_index): field_list = [String('%d' % i) for i in range(20)] field_list[expected_index] = self.get_original_field() uut = self.get_default_field() t = Container(name='level1', fields=[uut, Container(name='level2', fields=field_list)]) rendered = uut.render().tobytes() result = unpack('>I', rendered)[0] self.assertEqual(result, expected_index) del t def testCorrectIndexFirst(self): self._testCorrectIndex(0) def testCorrectIndexMiddle(self): self._testCorrectIndex(10) def testCorrectIndexLast(self): self._testCorrectIndex(19) def testFieldNotRenderedAlone(self): expected_index = 0 uut = self.get_default_field() the_field = Static(name=self.depends_on_name, value='') t = Container(name='level1', fields=[uut, Container(name='level2', fields=the_field)]) rendered = uut.render().tobytes() result = unpack('>I', rendered)[0] self.assertEqual(result, expected_index) del t def testFieldNotRenderedWithOtherFields(self): expected_index = 3 uut = self.get_default_field() fields = [ Static(name=self.depends_on_name, value=''), Static('field1'), Static('field2'), Static('field3'), ] t = Container(name='level1', fields=[uut, Container(name='level2', fields=fields)]) rendered = uut.render().tobytes() result = unpack('>I', rendered)[0] self.assertEqual(result, expected_index) del t
def testLengthNegative(self): with self.assertRaises(KittyException): BitField(value=self.default_value, length=-1)
def testLengthZero(self): with self.assertRaises(KittyException): BitField(value=self.default_value, length=0)
def testLengthVerySmall(self): self._base_check(BitField(value=1, length=1))
# Configuration descriptor # Section 9.6.3, page 265 configuration_descriptor = Template( name='configuration_descriptor', fields=[ UInt8(name='bLength', value=9), UInt8(name='bDescriptorType', value=DescriptorType.configuration), SizeInBytes(name='wTotalLength', sized_field='/', length=16, encoder=ENC_INT_LE), ElementCount(name='bNumInterfaces', depends_on='interfaces', length=8), UInt8(name='bConfigurationValue', value=1), UInt8(name='iConfiguration', value=0), BitField(name='bmAttributes', value=0, length=8), UInt8(name='bMaxPower', value=1), List(name='interfaces', fields=[ Container( name='iface and eps', fields=[ SubDescriptor( name='interface_descriptor', descriptor_type=DescriptorType.interface, fields=[ UInt8(name='bInterfaceNumber', value=0), UInt8(name='bAlternateSetting', value=0), ElementCount(name='bNumEndpoints', depends_on='endpoints', length=8),