This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new dad4c402 test(python): add regression test for register_object 
__init__ wiring (#493)
dad4c402 is described below

commit dad4c402c1dbd8321a53f8f7501f227cbb067117
Author: Junru Shao <[email protected]>
AuthorDate: Sun Mar 1 19:03:55 2026 -0800

    test(python): add regression test for register_object __init__ wiring (#493)
    
    ## Summary
    
    Add a regression test for the `register_object` `__init__` wiring that
    prevents a NULL-handle segfault.
    
    ## Root Cause
    
    `CObject` (Cython extension type) has a custom `tp_new`, so CPython's
    `object.__init__` silently ignores extra positional arguments. Before
    `_install_init` was wired into `register_object` (#491), calling
    `TestIntPair(1, 2)` fell through to `object.__init__`, producing
    `chandle = NULL`. Any subsequent field access (e.g. `pair.a`)
    dereferences `chandle + field_offset` → **segfault**.
    
    ## Test Coverage
    
    The new `test_register_object_wires_init` verifies:
    
    1. Construction via the wired `__init__` yields a live (non-NULL) handle
    with correct field values.
    2. `__new__` alone leaves `chandle` at 0, confirming `__init__` is the
    only path that creates the C++ object.
    
    The test does not exercise the actual segfault (which would crash the
    runner); the NULL-handle assertion is the safe proxy.
    
    ## Test Plan
    
    - [x] `pytest -xvs
    tests/python/test_object.py::test_register_object_wires_init` — passed
---
 tests/python/test_object.py | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/tests/python/test_object.py b/tests/python/test_object.py
index afed61bf..74ced83b 100644
--- a/tests/python/test_object.py
+++ b/tests/python/test_object.py
@@ -153,6 +153,26 @@ def test_object_init() -> None:
     assert obj.v_i64 == 7  # ty: ignore[unresolved-attribute]
 
 
+def test_register_object_wires_init() -> None:
+    """Regression: register_object must wire __init__ from __ffi_init__.
+
+    Without _install_init in register_object, calling TestIntPair(1, 2)
+    falls through to object.__init__ which silently ignores args on
+    Cython extension types (CObject has custom tp_new).  The result is
+    chandle = NULL.  Any subsequent field access dereferences
+    chandle + offset → segfault.
+    """
+    # Construction must produce a live handle, not NULL.
+    pair = tvm_ffi.testing.TestIntPair(3, 7)
+    assert pair.__chandle__() != 0
+    assert pair.a == 3
+    assert pair.b == 7
+
+    # __new__ alone must NOT produce a usable object (chandle stays NULL).
+    bare = tvm_ffi.testing.TestIntPair.__new__(tvm_ffi.testing.TestIntPair)
+    assert bare.__chandle__() == 0
+
+
 def test_object_protocol() -> None:
     class CompactObject:
         def __init__(self, backend_obj: Any) -> None:

Reply via email to