]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
pybind/rbd: handle non-existent groups properly in list_snaps() 70039/head
authorVinayBhaskar-V <vvarada@redhat.com>
Thu, 9 Jul 2026 16:00:26 +0000 (21:30 +0530)
committerVinayBhaskar-V <vvarada@redhat.com>
Thu, 9 Jul 2026 16:16:21 +0000 (21:46 +0530)
Calling `list_snaps()` on a non-existent group crashed the entire
Python process with a `free(): invalid pointer` error. This happened
because an unexpected `-ENOENT` error returned by `rbd_group_snap_list2`
and the exception was raised without updating the num_group_snaps to 0
from 10. Later the Cython `__dealloc__` wrapper attempted to free garbage
of uninitialized pointer spaces resulting in a crash.

Fix this behavior by resetting `self.num_group_snaps` to 0 inside
`GroupSnapIterator` before raising exception to prevent memory
corruption and accessing uninitialized pointers during cleanup call

Now `list_snaps()` consistently raise an `ObjectNotFound` error when
invoked on a non-existent group.
Also Extended the `TestGroups` test fixture with `self.dne_group` to
validate the expected error path for `list_snaps()`.

Fixes: https://tracker.ceph.com/issues/78034
Signed-off-by: VinayBhaskar-V <vvarada@redhat.com>
src/pybind/rbd/rbd.pyx
src/test/pybind/test_rbd.py

index 57a11b7dc0cf784e52341b923e000a1b62b5860e..703b2f539eba260e826780e2ad86066efa81aa48 100644 (file)
@@ -6143,6 +6143,7 @@ cdef class GroupSnapIterator(object):
             if ret >= 0:
                 break
             elif ret != -errno.ERANGE:
+                self.num_group_snaps = 0
                 raise make_ex(ret, 'error listing snapshots for group %s' % group.name, group_errno_to_exception)
 
     def __iter__(self):
index f1d4f10e391be07ce4b417c79eed0d6824fff791..3bcadcb8481c8eacd3ba2d27239179f3a9c5ddee 100644 (file)
@@ -3078,6 +3078,7 @@ class TestGroups(object):
         create_group()
         snap_name = get_temp_snap_name()
         self.group = Group(ioctx, group_name)
+        self.dne_group = Group(ioctx, "group_does_not_exist")
 
     def teardown_method(self, method):
         remove_group()
@@ -3191,6 +3192,7 @@ class TestGroups(object):
 
     def test_group_snap(self):
         global snap_name
+        assert_raises(ObjectNotFound, self.dne_group.list_snaps)
         eq([], list(self.group.list_snaps()))
         self.group.create_snap(snap_name)
         eq([snap_name], [snap['name'] for snap in self.group.list_snaps()])