def _testStringsFromFile(self):
values = [
'It was the summer of 95 (so what!)',
'In the backyard, shaving the old plies',
'Feeling so strong (strong!), something went wrong (wrong!)',
'Straight into my finger, what a stinger, it was so long',
'I still remember that day, like the day that I said that I swear',
'"I\'ll never hurt myself again", but it seems that I\'m deemed to be wrong',
'To be wrong, to be wrong',
'Gotta keep holding on...they always played a slow song.',
]
filename = './kitty_strings.txt'
with open(filename, 'wb') as f:
f.write('\n'.join(values))
uut = String(name=self.uut_name, value='streetlight')
all_mutations = self.get_all_mutations(uut)
for value in values:
self.assertIn(Bits(bytes=value), all_mutations)
os.remove(filename)
python类Bits()的实例源码
def testConditionAppliesFirst(self):
field = self.get_condition_field()
condition = self.get_applies_first_condition()
inner_field = String(ConditionTest.inner_field_value)
condition_container = self.cls(condition=condition, fields=[inner_field], fuzzable=True)
# This is done to allow field name resolution
enclosing = Container(fields=[field, condition_container])
self.assertEqual(condition_container.render(), inner_field.render())
while condition_container.mutate():
self.assertEqual(condition_container.render(), inner_field.render())
condition_container.reset()
field.mutate()
self.assertEqual(condition_container.render(), Bits())
while condition_container.mutate():
self.assertEqual(condition_container.render(), Bits())
del enclosing
def testConditionNotAppliesFirst(self):
field = self.get_condition_field()
condition = self.get_not_applies_first_condition()
inner_field = String(ConditionTest.inner_field_value)
condition_container = self.cls(condition=condition, fields=[inner_field], fuzzable=True)
# This is done to allow field name resolution
enclosing = Container(fields=[field, condition_container])
self.assertEqual(condition_container.render(), Bits())
while condition_container.mutate():
self.assertEqual(condition_container.render(), Bits())
condition_container.reset()
field.mutate()
self.assertEqual(condition_container.render(), inner_field.render())
while condition_container.mutate():
self.assertEqual(condition_container.render(), inner_field.render())
del enclosing
def render(self, ctx=None):
'''
Render the current value into a :class:`bitstring.Bits` object
:rtype: :class:`bitstring.Bits`
:return: the rendered field
'''
self._initialize()
if ctx is None:
ctx = RenderContext()
#
# if we are called from within render, return a dummy object...
#
if self in ctx:
self._current_rendered = self._in_render_value()
else:
ctx.push(self)
if self.dependency_type == Calculated.VALUE_BASED:
self._rendered_field = self._field.render(ctx)
self._render()
ctx.pop()
return self._current_rendered
def __init__(self, depends_on, func, encoder=ENC_BITS_DEFAULT, fuzzable=True, name=None):
'''
:param depends_on: (name of) field we depend on
:type encoder: :class:`~kitty.model.low_level.encoder.BitsEncoder`
:param func: function for processing of the dependant data. func(Bits)->Bits
:param encoder: encoder for the field
:param fuzzable: is container fuzzable
:param name: (unique) name of the container
'''
try:
res = func(empty_bits)
kassert.is_of_types(res, Bits)
self._func = func
except:
raise KittyException('func should be func(Bits)->Bits')
super(CalculatedBits, self).__init__(depends_on=depends_on, encoder=encoder, fuzzable=fuzzable, name=name)
def render(self, ctx=None):
'''
Only render if condition applies
:param ctx: rendering context in which the method was called
:rtype: `Bits`
:return: rendered value of the container
'''
if ctx is None:
ctx = RenderContext()
self._initialize()
if self in ctx:
self._current_rendered = self._in_render_value()
else:
ctx.push(self)
if self._evaluate_condition(ctx):
super(Conditional, self).render(ctx)
else:
self.set_current_value(empty_bits)
ctx.pop()
return self._current_rendered
def __init__(self, pad_length, pad_data='\x00', fields=[], fuzzable=True, name=None):
'''
:param pad_length: length to pad up to (in bits)
:param pad_data: data to pad with (default: '\x00')
:param fields: enclosed field(s) (default: [])
:param fuzzable: is fuzzable (default: True)
:param name: (unique) name of the template (default: None)
:example:
Pad a string with ' 's so it is at least 20 bytes
::
Pad(fields=String('padded'), pad_data=' ', pad_length=20)
# default result will be: 'padded '
'''
super(Pad, self).__init__(fields=fields, encoder=ENC_BITS_DEFAULT, fuzzable=fuzzable, name=name)
self._pad_length = pad_length
self._pad_data = Bits(bytes=pad_data)
def render(self, ctx=None):
'''
Render only the mutated field (or the first one if not in mutation)
:param ctx: rendering context in which the method was called
:rtype: `Bits`
:return: rendered value of the container
'''
if ctx is None:
ctx = RenderContext()
ctx.push(self)
self._initialize()
offset = self.offset if self.offset else 0
self._fields[self._field_idx].set_offset(offset)
rendered = self._fields[self._field_idx].render(ctx)
self.set_current_value(rendered)
ctx.pop()
return self._current_rendered
def __init__(self, value, num_bits=1, fuzzable=True, name=None):
'''
:param value: value to mutate (str)
:param num_bits: number of consequtive bits to flip (invert)
:param fuzzable: is field fuzzable (default: True)
:param name: name of the object (default: None)
:raises: ``KittyException`` if num_bits is bigger than the value length in bits
:raises: ``KittyException`` if num_bits is not positive
'''
kassert.is_of_types(value, types.StringTypes)
if len(value) * 8 < num_bits:
raise KittyException('len of value in bits(%d) < num_bits(%d)' % (len(value) * 8, num_bits))
if num_bits <= 0:
raise KittyException('num_bits(%d) <= 0' % (num_bits))
super(BitFlip, self).__init__(value=Bits(bytes=value), encoder=ENC_BITS_DEFAULT, fuzzable=fuzzable, name=name)
self._data_len = len(value) * 8
self._num_bits = num_bits
self._num_mutations = self._data_len - (num_bits - 1)
def render(self, ctx=None):
'''
Render the current value into a :class:`bitstring.Bits` object
:rtype: :class:`bitstring.Bits`
:return: the rendered field
'''
self._initialize()
if ctx is None:
ctx = RenderContext()
#
# if we are called from within render, return a dummy object...
#
if self in ctx:
self._current_rendered = self._in_render_value()
else:
ctx.push(self)
if self.dependency_type == Calculated.VALUE_BASED:
self._rendered_field = self._field.render(ctx)
self._render()
ctx.pop()
return self._current_rendered
def __init__(self, depends_on, func, encoder=ENC_BITS_DEFAULT, fuzzable=True, name=None):
'''
:param depends_on: (name of) field we depend on
:type encoder: :class:`~kitty.model.low_level.encoder.BitsEncoder`
:param func: function for processing of the dependant data. func(Bits)->Bits
:param encoder: encoder for the field
:param fuzzable: is container fuzzable
:param name: (unique) name of the container
'''
try:
res = func(empty_bits)
kassert.is_of_types(res, Bits)
self._func = func
except:
raise KittyException('func should be func(Bits)->Bits')
super(CalculatedBits, self).__init__(depends_on=depends_on, encoder=encoder, fuzzable=fuzzable, name=name)
def render(self, ctx=None):
'''
Only render if condition applies
:param ctx: rendering context in which the method was called
:rtype: `Bits`
:return: rendered value of the container
'''
if ctx is None:
ctx = RenderContext()
self._initialize()
if self in ctx:
self._current_rendered = self._in_render_value()
else:
ctx.push(self)
if self._evaluate_condition(ctx):
super(Conditional, self).render(ctx)
else:
self.set_current_value(empty_bits)
ctx.pop()
return self._current_rendered
def __init__(self, pad_length, pad_data='\x00', fields=[], fuzzable=True, name=None):
'''
:param pad_length: length to pad up to (in bits)
:param pad_data: data to pad with (default: '\x00')
:param fields: enclosed field(s) (default: [])
:param fuzzable: is fuzzable (default: True)
:param name: (unique) name of the template (default: None)
:example:
Pad a string with ' 's so it is at least 20 bytes
::
Pad(fields=String('padded'), pad_data=' ', pad_length=20)
# default result will be: 'padded '
'''
super(Pad, self).__init__(fields=fields, encoder=ENC_BITS_DEFAULT, fuzzable=fuzzable, name=name)
self._pad_length = pad_length
self._pad_data = Bits(bytes=pad_data)
def __init__(self, value, num_bits=1, fuzzable=True, name=None):
'''
:param value: value to mutate (str)
:param num_bits: number of consequtive bits to flip (invert)
:param fuzzable: is field fuzzable (default: True)
:param name: name of the object (default: None)
:raises: ``KittyException`` if num_bits is bigger than the value length in bits
:raises: ``KittyException`` if num_bits is not positive
'''
kassert.is_of_types(value, types.StringTypes)
if len(value) * 8 < num_bits:
raise KittyException('len of value in bits(%d) < num_bits(%d)' % (len(value) * 8, num_bits))
if num_bits <= 0:
raise KittyException('num_bits(%d) <= 0' % (num_bits))
super(BitFlip, self).__init__(value=Bits(bytes=value), encoder=ENC_BITS_DEFAULT, fuzzable=fuzzable, name=name)
self._data_len = len(value) * 8
self._num_bits = num_bits
self._num_mutations = self._data_len - (num_bits - 1)
def write_bytes(self, value, nbytes=None):
import bitstring
# TODO: strings are utf-8 from json reading
if isinstance(value, six.text_type):
value = value.encode('latin-1')
value_len = len(value)
# Ensure the string is under the required data width
if nbytes is None:
nbytes = value_len
else:
if value_len > nbytes:
value = value[:nbytes]
elif value_len < nbytes:
value += b' ' * (nbytes - value_len)
# Cannot use string format shortcut, i.e. 'bytes:{}={}' due to the
# automatic whitespace trimming by bitstring.
self.bit_stream += bitstring.Bits(bytes=value)
return value
def pack_glyph(glyph, ili9341_t3_font):
glyph_bits = BitString()
header = glyph['header']
glyph_bits.append(Bits(uint=header['encoding'], length=3))
glyph_bits.append(Bits(uint=header['width'], length=ili9341_t3_font['bits_width']))
glyph_bits.append(Bits(uint=header['height'], length=ili9341_t3_font['bits_height']))
glyph_bits.append(Bits(int=header['xoffset'], length=ili9341_t3_font['bits_xoffset']))
glyph_bits.append(Bits(int=header['yoffset'], length=ili9341_t3_font['bits_yoffset']))
glyph_bits.append(Bits(uint=header['delta'], length=ili9341_t3_font['bits_delta']))
for row in glyph['data']:
if row['repeat'] == 0:
glyph_bits.append(Bits(bool=False))
else:
glyph_bits.append(Bits(bool=True))
glyph_bits.append(Bits(uint=row['repeat'] - 1, length=3))
for bit in row['bits']:
glyph_bits.append(Bits(bool=bit == 1))
glyph_bytes = glyph_bits.tobytes()
return glyph_bytes
def unpack(self, data):
if not isinstance(data, _Bits):
data = _Bits(data)
for i in range(self.count):
offset = i*self.size
try:
b = data[offset:offset + self.size]
self._values[i] = self.logical_range.scale_to(self.physical_range, b.int if self.logical_range.minimum<0 else b.uint)
except ArithmeticError:
# If the value is outside of the logical range, and NULLs are allowed, then do not modify the value
if not self.flags & ReportFlags.NULL_STATE:
raise
def deserialize(self, data, report_type: ReportType):
offset = 0
if not isinstance(data, _Bits):
data = _Bits(data)
for item in self.items:
if isinstance(item, Report):
if item.report_type is not report_type:
continue
item.unpack(data[offset:offset + item.bits])
else:
item.deserialize(data[offset:offset + item.bits], report_type)
offset += item.bits
def testSessionDataNotFuzzable(self):
field = self.cls(key=self.key_exists, default_value=self.default_value)
self.assertEqual(self.default_value_rendered, field.render())
field.set_session_data(self.default_session_data)
self.assertEqual(Bits(bytes=self.value_exists), field.render())
self.assertEqual(Bits(bytes=self.value_exists), field.render())
def testSessionDataNotFuzzableAfterReset(self):
field = self.cls(key=self.key_exists, default_value=self.default_value)
self.assertEqual(self.default_value_rendered, field.render())
field.set_session_data(self.default_session_data)
self.assertEqual(Bits(bytes=self.value_exists), field.render())
field.reset()
self.assertEqual(self.default_value_rendered, field.render())
def testSessionDataNotFuzzableDataChangeKeyExists(self):
field = self.cls(key=self.key_exists, default_value=self.default_value)
self.assertEqual(self.default_value_rendered, field.render())
field.set_session_data(self.default_session_data)
self.assertEqual(Bits(bytes=self.value_exists), field.render())
new_val = 'new value'
field.set_session_data({self.key_exists: new_val})
self.assertEqual(Bits(bytes=new_val), field.render())
def testSessionDataNotFuzzableDataChangeKeyNotExist(self):
field = self.cls(key=self.key_exists, default_value=self.default_value)
self.assertEqual(self.default_value_rendered, field.render())
field.set_session_data(self.default_session_data)
self.assertEqual(Bits(bytes=self.value_exists), field.render())
new_val = 'new value'
field.set_session_data({self.key_not_exist: new_val})
self.assertEqual(Bits(bytes=self.value_exists), field.render())
def testSessionDataFuzzableDataChangeKeyExists(self):
field = self.cls(key=self.key_exists, default_value=self.default_value, length=len(self.default_value), fuzzable=True)
self.assertEqual(self.default_value_rendered, field.render())
field.set_session_data(self.default_session_data)
self.assertEqual(Bits(bytes=self.value_exists), field.render())
new_val = 'new value'
field.set_session_data({self.key_exists: new_val})
self.assertEqual(Bits(bytes=new_val), field.render())
def testSessionDataFuzzableDataChangeKeyNotExist(self):
field = self.cls(key=self.key_exists, default_value=self.default_value, length=len(self.default_value), fuzzable=True)
self.assertEqual(self.default_value_rendered, field.render())
field.set_session_data(self.default_session_data)
self.assertEqual(Bits(bytes=self.value_exists), field.render())
new_val = 'new value'
field.set_session_data({self.key_not_exist: new_val})
self.assertEqual(Bits(bytes=self.value_exists), field.render())
def testMutations(self):
field = self.get_default_field()
mutations = self._get_all_mutations(field)
self.assertListEqual([Bits(bytes=x) for x in self.default_values], mutations)
mutations = self._get_all_mutations(field)
self.assertListEqual([Bits(bytes=x) for x in self.default_values], mutations)
def testExceptionWhenFuncReturnsBits(self):
def func(s):
return Bits('')
with self.assertRaises(KittyException):
self.get_default_field(func=func)
def calculate(self, field):
value = field.render()
digest = self.hasher(value.bytes).digest()
return Bits(bytes=digest)
def testInvalidHashFunctionReturnsBits(self):
def func(data):
return Bits()
with self.assertRaises(KittyException):
Hash(self.depends_on_name, algorithm='boom')
def _encode_func(self, value):
return Bits(bytes=pack(self.fmt, value))
def testZero(self):
uut = BitFieldMultiByteEncoder()
self.assertEqual(uut.encode(0, 10, False), Bits(bytes='\x00'))