Skip to content

Commit 8811218

Browse files
committed
Add tp_setattr/o to slots_fuzzer
1 parent 98f7ad3 commit 8811218

File tree

1 file changed

+66
-5
lines changed

1 file changed

+66
-5
lines changed

scripts/slot_fuzzer.py

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ def test(fun, name):
7878
else:
7979
print(type(e))
8080
81+
def test_dunder(obj, fun_name, *args):
82+
# avoid going through tp_getattr/o, which may be overridden to something funky
83+
args_str = ','.join([repr(x) for x in args])
84+
test(lambda: Klass.__dict__[fun_name](obj, *args), f"{fun_name} via class dict")
85+
test(lambda: getattr(obj, fun_name)(*args), f"{fun_name}")
86+
87+
def write_attr(obj, attr, value):
88+
if attr == 'foo':
89+
obj.foo = value
90+
elif attr == 'bar':
91+
obj.bar = value
92+
8193
obj = Klass()
8294
test(lambda: bool(obj), "bool(obj)")
8395
test(lambda: len(obj), "len(obj)")
@@ -86,10 +98,23 @@ def test(fun, name):
8698
test(lambda: obj.foo, "obj.foo")
8799
test(lambda: obj.bar, "obj.bar")
88100
101+
test(lambda: write_attr(obj, 'foo', 42), "obj.foo = 42")
102+
test(lambda: obj.foo, "obj.foo")
103+
test(lambda: write_attr(obj, 'foo', 'hello'), "obj.foo = 'hello'")
104+
test(lambda: obj.foo, "obj.foo")
105+
106+
test(lambda: write_attr(obj, 'bar', 42), "obj.bar = 42")
107+
test(lambda: obj.foo, "obj.foo")
108+
test(lambda: obj.bar, "obj.bar")
109+
89110
test(lambda: obj.__bool__(), "obj.__bool__()")
90111
test(lambda: obj.__len__(), "obj.__len__()")
91112
test(lambda: obj.__getattr__('bar'), "obj.__getattr__('bar')")
92113
test(lambda: obj.__getattribute__('bar'), "obj.__getattribute__('bar')")
114+
test(lambda: obj.__setattr__('foo', 11), "obj.__setattr__('foo', 11)")
115+
test(lambda: obj.__getattr__('foo'), "obj.__getattr__('foo')")
116+
test(lambda: obj.__delattr__('foo'), "obj.__delattr__('foo')")
117+
test(lambda: obj.__getattr__('foo'), "obj.__getattr__('foo')")
93118
94119
class Dummy1:
95120
pass
@@ -143,6 +168,14 @@ def compile_ext(name):
143168
)
144169
'''
145170

171+
# language=C
172+
C_SOURCE_HEADER = '''
173+
#include <Python.h>
174+
175+
PyObject *global_stash1;
176+
PyObject *global_stash2;
177+
'''
178+
146179

147180
def write_all(filename, text):
148181
with open(filename, 'w+') as f:
@@ -182,10 +215,38 @@ def tp_decl(self, name_prefix):
182215
Slot('tp_as_number', 'nb_bool', 'int $name$(PyObject* self)', ['1', '0', None]),
183216
Slot('tp_as_sequence', 'sq_length', 'Py_ssize_t $name$(PyObject* self)', ['0', '1', '42', None]),
184217
Slot('tp_as_mapping', 'mp_length', 'Py_ssize_t $name$(PyObject* self)', ['0', '1', '42', None]),
185-
Slot(NO_GROUP, 'tp_getattr', 'PyObject* $name$(PyObject* self, char *name)', ['Py_RETURN_NONE', 'Py_RETURN_TRUE', 'Py_NewRef(self)', None]),
186-
Slot(NO_GROUP, 'tp_getattro', 'PyObject* $name$(PyObject* self, PyObject *name)', ['Py_RETURN_NONE', 'Py_RETURN_TRUE', 'Py_NewRef(self)', None]),
187-
Slot(NO_GROUP, 'tp_descr_get', 'PyObject* $name$(PyObject* self, PyObject* key, PyObject* type)', ['Py_RETURN_NONE', 'Py_NewRef(key)', None]),
188-
Slot(NO_GROUP, 'tp_descr_set', 'int $name$(PyObject* self, PyObject* key, PyObject* value)', ['0', None])
218+
Slot(NO_GROUP, 'tp_getattr', 'PyObject* $name$(PyObject* self, char *name)', ['Py_RETURN_NONE', 'Py_RETURN_TRUE', 'Py_NewRef(self)', None,
219+
'''
220+
if (global_stash1 == NULL) Py_RETURN_NONE;
221+
Py_IncRef(global_stash1);
222+
return global_stash1;
223+
''']),
224+
Slot(NO_GROUP, 'tp_getattro', 'PyObject* $name$(PyObject* self, PyObject *name)', ['Py_RETURN_NONE', 'Py_RETURN_TRUE', 'Py_NewRef(self)', 'Py_NewRef(name)', None,
225+
'''
226+
if (global_stash1 == NULL) Py_RETURN_NONE;
227+
Py_IncRef(global_stash1);
228+
return global_stash1;
229+
''']),
230+
Slot(NO_GROUP, 'tp_setattro', 'PyObject* $name$(PyObject* self, PyObject *name, PyObject *value)', ['0', None,
231+
'''
232+
Py_IncRef(value);
233+
Py_XDECREF(global_stash1);
234+
global_stash1 = value;
235+
return 0;
236+
''']),
237+
Slot(NO_GROUP, 'tp_descr_get', 'PyObject* $name$(PyObject* self, PyObject* key, PyObject* type)', ['Py_RETURN_NONE', 'Py_NewRef(key)', None,
238+
'''
239+
if (global_stash2 == NULL) Py_RETURN_NONE;
240+
Py_IncRef(global_stash2);
241+
return global_stash2;
242+
''']),
243+
Slot(NO_GROUP, 'tp_descr_set', 'int $name$(PyObject* self, PyObject* key, PyObject* value)', ['0', None,
244+
'''
245+
Py_IncRef(value);
246+
Py_XDECREF(global_stash2);
247+
global_stash2 = value;
248+
return 0;
249+
'''])
189250
]
190251

191252

@@ -362,7 +423,7 @@ def choose_random(l):
362423
classes_count = max(3, rand.randint(1, 5)) # Make it more likely that it's 3...
363424
classes = []
364425
test_module_name = f"test{test_case_idx}"
365-
c_source = '#include <Python.h>\n\n'
426+
c_source = C_SOURCE_HEADER
366427
py_source = SLOTS_TESTER
367428
native_classes = []
368429
for i in range(classes_count):

0 commit comments

Comments
 (0)