commit
2b78d0bd2c
6 changed files with 591 additions and 7 deletions
|
|
@ -1,20 +1,601 @@
|
||||||
"""fuzz_property_types - stub. Wave 2 agent W5 will implement.
|
"""fuzz_property_types - property getter/setter fuzzing across all UI types.
|
||||||
|
|
||||||
Target bugs: #267 (PyObject_GetAttrString reference leaks), #268
|
Targets:
|
||||||
(sfVector2f_to_PyObject NULL deref), #272 (UniformCollection unchecked
|
#267 - PyObject_GetAttrString reference leaks (60+ sites)
|
||||||
weak_ptr). Random property get/set with type confusion across all UI types.
|
#268 - sfVector2f_to_PyObject NULL deref on bad Vector setters
|
||||||
|
#272 - UniformCollection unchecked weak_ptr
|
||||||
|
|
||||||
Contract: define fuzz_one_input(data: bytes) -> None.
|
Strategy:
|
||||||
|
Each iteration creates a mix of Frame/Caption/Sprite/Grid/Entity/
|
||||||
|
TileLayer/ColorLayer/Color/Vector instances and hammers their
|
||||||
|
properties with both correct-type values (stressing refcount sites)
|
||||||
|
and deliberately wrong-type values (stressing setter error paths).
|
||||||
|
|
||||||
|
Hot-loop repeated GetAttrString reads exercise the #267 refcount
|
||||||
|
site density. Wrong-type writes exercise #268 and setter NULL
|
||||||
|
returns. Nested frame + reparenting stresses parent/children bookkeeping.
|
||||||
|
|
||||||
|
Contract: fuzz_one_input(data: bytes) -> None, wrapped in EXPECTED_EXCEPTIONS.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import mcrfpy
|
import mcrfpy
|
||||||
|
|
||||||
from fuzz_common import ByteStream, EXPECTED_EXCEPTIONS
|
from fuzz_common import ByteStream, EXPECTED_EXCEPTIONS, safe_reset
|
||||||
|
|
||||||
|
MAX_OPS = 40
|
||||||
|
HOT_LOOP = 60
|
||||||
|
|
||||||
|
# Property groups verified against src/UIFrame.cpp, src/UICaption.cpp,
|
||||||
|
# src/UISprite.cpp, src/UIGridPyProperties.cpp, src/UIEntity.cpp,
|
||||||
|
# src/GridLayers.cpp, src/PyColor.cpp, src/PyVector.cpp.
|
||||||
|
|
||||||
|
FRAME_FLOAT_PROPS = ("x", "y", "w", "h", "outline", "opacity", "rotation")
|
||||||
|
FRAME_INT_PROPS = ("z_index",)
|
||||||
|
FRAME_BOOL_PROPS = ("visible", "clip_children", "cache_subtree")
|
||||||
|
FRAME_COLOR_PROPS = ("fill_color", "outline_color")
|
||||||
|
FRAME_VECTOR_PROPS = ("pos", "origin")
|
||||||
|
FRAME_STR_PROPS = ("name",)
|
||||||
|
FRAME_ALL_READ = (
|
||||||
|
FRAME_FLOAT_PROPS + FRAME_INT_PROPS + FRAME_BOOL_PROPS
|
||||||
|
+ FRAME_COLOR_PROPS + FRAME_VECTOR_PROPS + FRAME_STR_PROPS
|
||||||
|
+ ("children", "parent", "global_position", "bounds", "global_bounds",
|
||||||
|
"hovered", "shader", "uniforms", "align", "margin",
|
||||||
|
"horiz_margin", "vert_margin")
|
||||||
|
)
|
||||||
|
|
||||||
|
CAPTION_FLOAT_PROPS = ("x", "y", "outline", "opacity", "rotation", "font_size")
|
||||||
|
CAPTION_INT_PROPS = ("z_index",)
|
||||||
|
CAPTION_BOOL_PROPS = ("visible",)
|
||||||
|
CAPTION_COLOR_PROPS = ("fill_color", "outline_color")
|
||||||
|
CAPTION_VECTOR_PROPS = ("pos", "origin")
|
||||||
|
CAPTION_STR_PROPS = ("name", "text")
|
||||||
|
|
||||||
|
SPRITE_FLOAT_PROPS = ("x", "y", "scale", "scale_x", "scale_y", "opacity", "rotation")
|
||||||
|
SPRITE_INT_PROPS = ("z_index", "sprite_index")
|
||||||
|
SPRITE_BOOL_PROPS = ("visible",)
|
||||||
|
SPRITE_VECTOR_PROPS = ("pos", "origin")
|
||||||
|
SPRITE_STR_PROPS = ("name",)
|
||||||
|
|
||||||
|
GRID_FLOAT_PROPS = ("x", "y", "w", "h", "center_x", "center_y", "zoom",
|
||||||
|
"camera_rotation", "opacity", "rotation")
|
||||||
|
GRID_INT_PROPS = ("z_index", "fov_radius")
|
||||||
|
GRID_BOOL_PROPS = ("visible", "perspective_enabled")
|
||||||
|
GRID_VECTOR_PROPS = ("pos", "size", "center", "origin")
|
||||||
|
GRID_COLOR_PROPS = ("fill_color",)
|
||||||
|
GRID_STR_PROPS = ("name",)
|
||||||
|
|
||||||
|
ENTITY_FLOAT_PROPS = ("x", "y", "opacity", "move_speed")
|
||||||
|
ENTITY_INT_PROPS = ("sprite_index", "cell_x", "cell_y", "grid_x", "grid_y",
|
||||||
|
"tile_width", "tile_height", "default_behavior",
|
||||||
|
"turn_order", "sight_radius")
|
||||||
|
ENTITY_BOOL_PROPS = ("visible",)
|
||||||
|
ENTITY_VECTOR_PROPS = ("pos", "cell_pos", "grid_pos", "draw_pos",
|
||||||
|
"sprite_offset", "tile_size")
|
||||||
|
ENTITY_STR_PROPS = ("name", "target_label")
|
||||||
|
|
||||||
|
TILELAYER_INT_PROPS = ("z_index",)
|
||||||
|
TILELAYER_BOOL_PROPS = ("visible",)
|
||||||
|
|
||||||
|
COLORLAYER_INT_PROPS = ("z_index",)
|
||||||
|
COLORLAYER_BOOL_PROPS = ("visible",)
|
||||||
|
|
||||||
|
|
||||||
|
def confused_value(stream):
|
||||||
|
"""Return a deliberately type-confused value for property setters.
|
||||||
|
|
||||||
|
Every branch returns something that is the 'wrong shape' for at
|
||||||
|
least one real setter. The fuzz loop catches TypeError/ValueError
|
||||||
|
so this flushes out places where setters NULL-deref or leak refs
|
||||||
|
on bad input rather than raising cleanly.
|
||||||
|
"""
|
||||||
|
which = stream.u8() % 12
|
||||||
|
if which == 0:
|
||||||
|
return None
|
||||||
|
if which == 1:
|
||||||
|
return stream.int_in_range(-1_000_000, 1_000_000)
|
||||||
|
if which == 2:
|
||||||
|
return stream.float_in_range(-1e9, 1e9)
|
||||||
|
if which == 3:
|
||||||
|
return stream.ascii_str(12)
|
||||||
|
if which == 4:
|
||||||
|
return stream.bool()
|
||||||
|
if which == 5:
|
||||||
|
return ()
|
||||||
|
if which == 6:
|
||||||
|
return (stream.float_in_range(-100, 100), stream.float_in_range(-100, 100))
|
||||||
|
if which == 7:
|
||||||
|
return [stream.u8() for _ in range(stream.int_in_range(0, 5))]
|
||||||
|
if which == 8:
|
||||||
|
return {"x": 1, "y": 2}
|
||||||
|
if which == 9:
|
||||||
|
# Incomplete color tuple - exercises PyColor::fromPy error paths
|
||||||
|
return (stream.int_in_range(-50, 300), stream.int_in_range(-50, 300), stream.int_in_range(-50, 300))
|
||||||
|
if which == 10:
|
||||||
|
# float specials that can surprise clamping / isnan checks
|
||||||
|
variant = stream.u8() % 4
|
||||||
|
if variant == 0:
|
||||||
|
return float("inf")
|
||||||
|
if variant == 1:
|
||||||
|
return float("-inf")
|
||||||
|
if variant == 2:
|
||||||
|
return float("nan")
|
||||||
|
return 0.0
|
||||||
|
return object() # bare object with no protocol
|
||||||
|
|
||||||
|
|
||||||
|
def _safe_texture():
|
||||||
|
"""Return mcrfpy.default_texture or None. Never raises."""
|
||||||
|
try:
|
||||||
|
return getattr(mcrfpy, "default_texture", None)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _make_frame(stream):
|
||||||
|
x = stream.float_in_range(-200, 800)
|
||||||
|
y = stream.float_in_range(-200, 800)
|
||||||
|
w = stream.float_in_range(1, 400)
|
||||||
|
h = stream.float_in_range(1, 400)
|
||||||
|
return mcrfpy.Frame(pos=(x, y), size=(w, h))
|
||||||
|
|
||||||
|
|
||||||
|
def _make_caption(stream):
|
||||||
|
x = stream.float_in_range(-200, 800)
|
||||||
|
y = stream.float_in_range(-200, 800)
|
||||||
|
text = stream.ascii_str(20)
|
||||||
|
return mcrfpy.Caption(text=text, pos=(x, y))
|
||||||
|
|
||||||
|
|
||||||
|
def _make_sprite(stream):
|
||||||
|
x = stream.float_in_range(-200, 800)
|
||||||
|
y = stream.float_in_range(-200, 800)
|
||||||
|
tex = _safe_texture()
|
||||||
|
if tex is not None:
|
||||||
|
return mcrfpy.Sprite(pos=(x, y), texture=tex)
|
||||||
|
return mcrfpy.Sprite(pos=(x, y))
|
||||||
|
|
||||||
|
|
||||||
|
def _make_grid(stream):
|
||||||
|
gw = stream.int_in_range(1, 40)
|
||||||
|
gh = stream.int_in_range(1, 40)
|
||||||
|
return mcrfpy.Grid(grid_size=(gw, gh))
|
||||||
|
|
||||||
|
|
||||||
|
def _make_entity(stream):
|
||||||
|
gx = stream.int_in_range(-5, 40)
|
||||||
|
gy = stream.int_in_range(-5, 40)
|
||||||
|
return mcrfpy.Entity(grid_pos=(gx, gy))
|
||||||
|
|
||||||
|
|
||||||
|
def _make_tilelayer(stream):
|
||||||
|
z = stream.int_in_range(-10, 10)
|
||||||
|
tex = _safe_texture()
|
||||||
|
name = stream.ascii_str(8) or "tile"
|
||||||
|
if tex is not None:
|
||||||
|
return mcrfpy.TileLayer(name=name, z_index=z, texture=tex)
|
||||||
|
return mcrfpy.TileLayer(name=name, z_index=z)
|
||||||
|
|
||||||
|
|
||||||
|
def _make_colorlayer(stream):
|
||||||
|
z = stream.int_in_range(-10, 10)
|
||||||
|
name = stream.ascii_str(8) or "color"
|
||||||
|
return mcrfpy.ColorLayer(name=name, z_index=z)
|
||||||
|
|
||||||
|
|
||||||
|
def _good_value_for(stream, prop_type):
|
||||||
|
"""Return a well-typed value for the named property kind."""
|
||||||
|
if prop_type == "float":
|
||||||
|
return stream.float_in_range(-1000, 1000)
|
||||||
|
if prop_type == "int":
|
||||||
|
return stream.int_in_range(-100, 100)
|
||||||
|
if prop_type == "bool":
|
||||||
|
return stream.bool()
|
||||||
|
if prop_type == "vector":
|
||||||
|
return (stream.float_in_range(-500, 500), stream.float_in_range(-500, 500))
|
||||||
|
if prop_type == "color":
|
||||||
|
return (
|
||||||
|
stream.int_in_range(0, 255),
|
||||||
|
stream.int_in_range(0, 255),
|
||||||
|
stream.int_in_range(0, 255),
|
||||||
|
stream.int_in_range(0, 255),
|
||||||
|
)
|
||||||
|
if prop_type == "str":
|
||||||
|
return stream.ascii_str(16)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _read_all(obj, names):
|
||||||
|
"""Hot-loop getter reads. Exercises PyObject_GetAttrString refcount sites."""
|
||||||
|
for name in names:
|
||||||
|
try:
|
||||||
|
_ = getattr(obj, name)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _write_correct(stream, obj, groups):
|
||||||
|
"""Write every property in groups with well-typed values."""
|
||||||
|
for prop_type, names in groups:
|
||||||
|
for name in names:
|
||||||
|
try:
|
||||||
|
setattr(obj, name, _good_value_for(stream, prop_type))
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _write_confused(stream, obj, all_names):
|
||||||
|
"""Pick a property and write a type-confused value."""
|
||||||
|
if not all_names:
|
||||||
|
return
|
||||||
|
name = stream.pick_one(all_names)
|
||||||
|
try:
|
||||||
|
setattr(obj, name, confused_value(stream))
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ----- Per-type operations -----
|
||||||
|
|
||||||
|
def fuzz_frame_correct(stream):
|
||||||
|
f = _make_frame(stream)
|
||||||
|
groups = (
|
||||||
|
("float", FRAME_FLOAT_PROPS),
|
||||||
|
("int", FRAME_INT_PROPS),
|
||||||
|
("bool", FRAME_BOOL_PROPS),
|
||||||
|
("color", FRAME_COLOR_PROPS),
|
||||||
|
("vector", FRAME_VECTOR_PROPS),
|
||||||
|
("str", FRAME_STR_PROPS),
|
||||||
|
)
|
||||||
|
_write_correct(stream, f, groups)
|
||||||
|
_read_all(f, FRAME_ALL_READ)
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_frame_confused(stream):
|
||||||
|
f = _make_frame(stream)
|
||||||
|
all_writable = (
|
||||||
|
FRAME_FLOAT_PROPS + FRAME_INT_PROPS + FRAME_BOOL_PROPS
|
||||||
|
+ FRAME_COLOR_PROPS + FRAME_VECTOR_PROPS + FRAME_STR_PROPS
|
||||||
|
+ ("parent", "shader", "align")
|
||||||
|
)
|
||||||
|
n = stream.int_in_range(1, 8)
|
||||||
|
for _ in range(n):
|
||||||
|
_write_confused(stream, f, all_writable)
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_caption_correct(stream):
|
||||||
|
c = _make_caption(stream)
|
||||||
|
groups = (
|
||||||
|
("float", CAPTION_FLOAT_PROPS),
|
||||||
|
("int", CAPTION_INT_PROPS),
|
||||||
|
("bool", CAPTION_BOOL_PROPS),
|
||||||
|
("color", CAPTION_COLOR_PROPS),
|
||||||
|
("vector", CAPTION_VECTOR_PROPS),
|
||||||
|
("str", CAPTION_STR_PROPS),
|
||||||
|
)
|
||||||
|
_write_correct(stream, c, groups)
|
||||||
|
_read_all(c, CAPTION_FLOAT_PROPS + CAPTION_INT_PROPS + CAPTION_BOOL_PROPS
|
||||||
|
+ CAPTION_COLOR_PROPS + CAPTION_VECTOR_PROPS + CAPTION_STR_PROPS
|
||||||
|
+ ("size", "w", "h"))
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_caption_confused(stream):
|
||||||
|
c = _make_caption(stream)
|
||||||
|
all_writable = (
|
||||||
|
CAPTION_FLOAT_PROPS + CAPTION_INT_PROPS + CAPTION_BOOL_PROPS
|
||||||
|
+ CAPTION_COLOR_PROPS + CAPTION_VECTOR_PROPS + CAPTION_STR_PROPS
|
||||||
|
)
|
||||||
|
n = stream.int_in_range(1, 8)
|
||||||
|
for _ in range(n):
|
||||||
|
_write_confused(stream, c, all_writable)
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_sprite_correct(stream):
|
||||||
|
s = _make_sprite(stream)
|
||||||
|
groups = (
|
||||||
|
("float", SPRITE_FLOAT_PROPS),
|
||||||
|
("int", SPRITE_INT_PROPS),
|
||||||
|
("bool", SPRITE_BOOL_PROPS),
|
||||||
|
("vector", SPRITE_VECTOR_PROPS),
|
||||||
|
("str", SPRITE_STR_PROPS),
|
||||||
|
)
|
||||||
|
_write_correct(stream, s, groups)
|
||||||
|
_read_all(s, SPRITE_FLOAT_PROPS + SPRITE_INT_PROPS + SPRITE_BOOL_PROPS
|
||||||
|
+ SPRITE_VECTOR_PROPS + SPRITE_STR_PROPS + ("texture",))
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_sprite_confused(stream):
|
||||||
|
s = _make_sprite(stream)
|
||||||
|
all_writable = (
|
||||||
|
SPRITE_FLOAT_PROPS + SPRITE_INT_PROPS + SPRITE_BOOL_PROPS
|
||||||
|
+ SPRITE_VECTOR_PROPS + SPRITE_STR_PROPS + ("texture",)
|
||||||
|
)
|
||||||
|
n = stream.int_in_range(1, 8)
|
||||||
|
for _ in range(n):
|
||||||
|
_write_confused(stream, s, all_writable)
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_grid_correct(stream):
|
||||||
|
g = _make_grid(stream)
|
||||||
|
groups = (
|
||||||
|
("float", GRID_FLOAT_PROPS),
|
||||||
|
("int", GRID_INT_PROPS),
|
||||||
|
("bool", GRID_BOOL_PROPS),
|
||||||
|
("vector", GRID_VECTOR_PROPS),
|
||||||
|
("color", GRID_COLOR_PROPS),
|
||||||
|
("str", GRID_STR_PROPS),
|
||||||
|
)
|
||||||
|
_write_correct(stream, g, groups)
|
||||||
|
_read_all(g, GRID_FLOAT_PROPS + GRID_INT_PROPS + GRID_BOOL_PROPS
|
||||||
|
+ GRID_VECTOR_PROPS + GRID_COLOR_PROPS + GRID_STR_PROPS
|
||||||
|
+ ("grid_size", "grid_w", "grid_h", "entities", "children",
|
||||||
|
"layers", "texture", "view", "hovered_cell"))
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_grid_confused(stream):
|
||||||
|
g = _make_grid(stream)
|
||||||
|
all_writable = (
|
||||||
|
GRID_FLOAT_PROPS + GRID_INT_PROPS + GRID_BOOL_PROPS
|
||||||
|
+ GRID_VECTOR_PROPS + GRID_COLOR_PROPS + GRID_STR_PROPS
|
||||||
|
+ ("perspective", "fov")
|
||||||
|
)
|
||||||
|
n = stream.int_in_range(1, 8)
|
||||||
|
for _ in range(n):
|
||||||
|
_write_confused(stream, g, all_writable)
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_entity_correct(stream):
|
||||||
|
e = _make_entity(stream)
|
||||||
|
groups = (
|
||||||
|
("float", ENTITY_FLOAT_PROPS),
|
||||||
|
("int", ENTITY_INT_PROPS),
|
||||||
|
("bool", ENTITY_BOOL_PROPS),
|
||||||
|
("vector", ENTITY_VECTOR_PROPS),
|
||||||
|
("str", ENTITY_STR_PROPS),
|
||||||
|
)
|
||||||
|
_write_correct(stream, e, groups)
|
||||||
|
_read_all(e, ENTITY_FLOAT_PROPS + ENTITY_INT_PROPS + ENTITY_BOOL_PROPS
|
||||||
|
+ ENTITY_VECTOR_PROPS + ENTITY_STR_PROPS
|
||||||
|
+ ("gridstate", "grid", "shader", "uniforms", "labels",
|
||||||
|
"behavior_type", "sprite_grid"))
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_entity_confused(stream):
|
||||||
|
e = _make_entity(stream)
|
||||||
|
all_writable = (
|
||||||
|
ENTITY_FLOAT_PROPS + ENTITY_INT_PROPS + ENTITY_BOOL_PROPS
|
||||||
|
+ ENTITY_VECTOR_PROPS + ENTITY_STR_PROPS
|
||||||
|
+ ("grid", "shader", "labels", "step", "sprite_grid")
|
||||||
|
)
|
||||||
|
n = stream.int_in_range(1, 8)
|
||||||
|
for _ in range(n):
|
||||||
|
_write_confused(stream, e, all_writable)
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_tilelayer(stream):
|
||||||
|
try:
|
||||||
|
layer = _make_tilelayer(stream)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
return
|
||||||
|
# Correct writes
|
||||||
|
for _ in range(stream.int_in_range(1, 4)):
|
||||||
|
try:
|
||||||
|
layer.z_index = stream.int_in_range(-20, 20)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
layer.visible = stream.bool()
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
# Read everything including read-only
|
||||||
|
_read_all(layer, ("z_index", "visible", "texture", "grid_size", "name", "grid"))
|
||||||
|
# Confused writes
|
||||||
|
_write_confused(stream, layer, ("z_index", "visible", "texture", "grid"))
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_colorlayer(stream):
|
||||||
|
try:
|
||||||
|
layer = _make_colorlayer(stream)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
return
|
||||||
|
for _ in range(stream.int_in_range(1, 4)):
|
||||||
|
try:
|
||||||
|
layer.z_index = stream.int_in_range(-20, 20)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
layer.visible = stream.bool()
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
_read_all(layer, ("z_index", "visible", "grid_size", "name", "grid"))
|
||||||
|
_write_confused(stream, layer, ("z_index", "visible", "grid"))
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_color(stream):
|
||||||
|
try:
|
||||||
|
c = mcrfpy.Color(
|
||||||
|
stream.int_in_range(0, 255),
|
||||||
|
stream.int_in_range(0, 255),
|
||||||
|
stream.int_in_range(0, 255),
|
||||||
|
stream.int_in_range(0, 255),
|
||||||
|
)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
return
|
||||||
|
# Hammer r/g/b/a in and out of 0-255
|
||||||
|
for _ in range(stream.int_in_range(4, 16)):
|
||||||
|
for prop in ("r", "g", "b", "a"):
|
||||||
|
try:
|
||||||
|
setattr(c, prop, stream.int_in_range(-500, 1000))
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
_ = getattr(c, prop)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
# Confused writes
|
||||||
|
for prop in ("r", "g", "b", "a"):
|
||||||
|
try:
|
||||||
|
setattr(c, prop, confused_value(stream))
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_vector(stream):
|
||||||
|
try:
|
||||||
|
v = mcrfpy.Vector(
|
||||||
|
stream.float_in_range(-1000, 1000),
|
||||||
|
stream.float_in_range(-1000, 1000),
|
||||||
|
)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
return
|
||||||
|
# Correct writes, including inf/nan specials
|
||||||
|
for _ in range(stream.int_in_range(4, 16)):
|
||||||
|
sel = stream.u8() % 5
|
||||||
|
if sel == 0:
|
||||||
|
val = float("inf")
|
||||||
|
elif sel == 1:
|
||||||
|
val = float("-inf")
|
||||||
|
elif sel == 2:
|
||||||
|
val = float("nan")
|
||||||
|
else:
|
||||||
|
val = stream.float_in_range(-1e6, 1e6)
|
||||||
|
try:
|
||||||
|
v.x = val
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
v.y = val
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
_ = v.x
|
||||||
|
_ = v.y
|
||||||
|
_ = v.int
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
# Confused writes
|
||||||
|
for prop in ("x", "y"):
|
||||||
|
try:
|
||||||
|
setattr(v, prop, confused_value(stream))
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_nested_reparent(stream):
|
||||||
|
"""Nest captions/sprites in frames, reparent between two frames.
|
||||||
|
|
||||||
|
Exercises UICollection parent bookkeeping and shared ownership edges.
|
||||||
|
"""
|
||||||
|
f1 = _make_frame(stream)
|
||||||
|
f2 = _make_frame(stream)
|
||||||
|
try:
|
||||||
|
f1.children.append(_make_caption(stream))
|
||||||
|
f1.children.append(_make_frame(stream))
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
f2.children.append(_make_caption(stream))
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
# Move child from f1 to f2 (if possible) via append/remove
|
||||||
|
try:
|
||||||
|
if len(f1.children) > 0:
|
||||||
|
child = f1.children[stream.int_in_range(0, len(f1.children) - 1)]
|
||||||
|
f2.children.append(child)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
# Hammer the nested frames' properties
|
||||||
|
for f in (f1, f2):
|
||||||
|
try:
|
||||||
|
f.x = stream.float_in_range(-100, 100)
|
||||||
|
f.y = stream.float_in_range(-100, 100)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
# Read children collection and walk it
|
||||||
|
try:
|
||||||
|
for child in f1.children:
|
||||||
|
_ = getattr(child, "x", None)
|
||||||
|
_ = getattr(child, "pos", None)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def fuzz_hot_loop_reads(stream):
|
||||||
|
"""Dense PyObject_GetAttrString reads to stress #267 sites."""
|
||||||
|
f = _make_frame(stream)
|
||||||
|
# Also try a Grid (different getter table)
|
||||||
|
g = _make_grid(stream)
|
||||||
|
e = _make_entity(stream)
|
||||||
|
# Tight loop reading many properties
|
||||||
|
for _ in range(HOT_LOOP):
|
||||||
|
try:
|
||||||
|
_ = f.pos
|
||||||
|
_ = f.fill_color
|
||||||
|
_ = f.outline_color
|
||||||
|
_ = f.x
|
||||||
|
_ = f.y
|
||||||
|
_ = f.w
|
||||||
|
_ = f.h
|
||||||
|
_ = f.visible
|
||||||
|
_ = f.opacity
|
||||||
|
_ = f.children
|
||||||
|
_ = f.bounds
|
||||||
|
_ = f.global_position
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
_ = g.pos
|
||||||
|
_ = g.size
|
||||||
|
_ = g.center
|
||||||
|
_ = g.grid_size
|
||||||
|
_ = g.fill_color
|
||||||
|
_ = g.entities
|
||||||
|
_ = g.layers
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
_ = e.pos
|
||||||
|
_ = e.cell_pos
|
||||||
|
_ = e.draw_pos
|
||||||
|
_ = e.grid_pos
|
||||||
|
_ = e.sprite_offset
|
||||||
|
_ = e.tile_size
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# ----- Dispatch -----
|
||||||
|
|
||||||
|
OPS = (
|
||||||
|
fuzz_frame_correct,
|
||||||
|
fuzz_frame_confused,
|
||||||
|
fuzz_caption_correct,
|
||||||
|
fuzz_caption_confused,
|
||||||
|
fuzz_sprite_correct,
|
||||||
|
fuzz_sprite_confused,
|
||||||
|
fuzz_grid_correct,
|
||||||
|
fuzz_grid_confused,
|
||||||
|
fuzz_entity_correct,
|
||||||
|
fuzz_entity_confused,
|
||||||
|
fuzz_tilelayer,
|
||||||
|
fuzz_colorlayer,
|
||||||
|
fuzz_color,
|
||||||
|
fuzz_vector,
|
||||||
|
fuzz_nested_reparent,
|
||||||
|
fuzz_hot_loop_reads,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def fuzz_one_input(data):
|
def fuzz_one_input(data):
|
||||||
stream = ByteStream(data)
|
stream = ByteStream(data)
|
||||||
try:
|
try:
|
||||||
mcrfpy.Frame(pos=(0, 0), size=(10, 10))
|
n = stream.int_in_range(1, MAX_OPS)
|
||||||
|
for _ in range(n):
|
||||||
|
if stream.remaining < 1:
|
||||||
|
break
|
||||||
|
op = OPS[stream.u8() % len(OPS)]
|
||||||
|
try:
|
||||||
|
op(stream)
|
||||||
|
except EXPECTED_EXCEPTIONS:
|
||||||
|
pass
|
||||||
except EXPECTED_EXCEPTIONS:
|
except EXPECTED_EXCEPTIONS:
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
1
tests/fuzz/seeds/property_types/seed_color_vector.bin
Normal file
1
tests/fuzz/seeds/property_types/seed_color_vector.bin
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
<20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD> <20><01><EFBFBD>
|
||||||
BIN
tests/fuzz/seeds/property_types/seed_frame_all_props.bin
Normal file
BIN
tests/fuzz/seeds/property_types/seed_frame_all_props.bin
Normal file
Binary file not shown.
1
tests/fuzz/seeds/property_types/seed_hot_loop.bin
Normal file
1
tests/fuzz/seeds/property_types/seed_hot_loop.bin
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
1
tests/fuzz/seeds/property_types/seed_nested.bin
Normal file
1
tests/fuzz/seeds/property_types/seed_nested.bin
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню"3DЛЬню
|
||||||
BIN
tests/fuzz/seeds/property_types/seed_wrong_types.bin
Normal file
BIN
tests/fuzz/seeds/property_types/seed_wrong_types.bin
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue