Double free of Colorspace used in Pixmap (original) (raw)
Describe the bug
When creating an empty Pixmap from a Colorspace object and IRect, the Colorspace gets freed twice and causes an invalid read leading to crashes.
To Reproduce (mandatory)
from fitz import IRect, Pixmap, CS_RGB, Colorspace
image = Pixmap(Colorspace(CS_RGB), IRect(0, 0, 13, 37))
(put that line in a while True if you want to make sure you get a crash eventually)
Screenshots
Valgrind output (PYMUPDF_SETUP_MUPDF_BUILD_TYPE=debug on tag 1.21.1):
==347882== Memcheck, a memory error detector
==347882== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==347882== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==347882== Command: python -u segfault_vg.py
==347882==
==347882== Invalid read of size 4
==347882== at 0x75F93EC: fz_drop_key_storable (store.c:195)
==347882== by 0x757387F: fz_drop_colorspace (colorspace.c:293)
==347882== by 0x7573343: fz_drop_colorspace_context (colorspace.c:132)
==347882== by 0x7578064: fz_drop_context (context.c:157)
==347882== by 0x4E81030: __run_exit_handlers (exit.c:108)
==347882== by 0x4E81129: exit (exit.c:139)
==347882== by 0x4E5FC8D: (below main) (libc-start.c:344)
==347882== Address 0x72f47f0 is 0 bytes inside a block of size 336 free'd
==347882== at 0x4C32D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==347882== by 0x75D147A: fz_free_default (memory.c:192)
==347882== by 0x75D13AB: fz_free (memory.c:163)
==347882== by 0x75739F8: fz_drop_colorspace_imp (colorspace.c:335)
==347882== by 0x75F94CA: fz_drop_key_storable (store.c:225)
==347882== by 0x757387F: fz_drop_colorspace (colorspace.c:293)
==347882== by 0x75E1334: fz_drop_pixmap_imp (pixmap.c:51)
==347882== by 0x75FAD4A: fz_drop_storable (store.c:906)
==347882== by 0x75E1302: fz_drop_pixmap (pixmap.c:43)
==347882== by 0x7530670: delete_Pixmap (fitz_wrap.c:15006)
==347882== by 0x7530670: _wrap_delete_Pixmap (fitz_wrap.c:25261)
==347882== by 0x548E78: cfunction_call.lto_priv.503 (methodobject.c:552)
==347882== by 0x5FA29B: _PyObject_MakeTpCall (call.c:191)
==347882== Block was alloc'd at
==347882== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==347882== by 0x75D1433: fz_malloc_default (memory.c:180)
==347882== by 0x75D0F55: do_scavenging_malloc (memory.c:51)
==347882== by 0x75D11AA: fz_calloc (memory.c:111)
==347882== by 0x7573A2A: fz_new_colorspace (colorspace.c:341)
==347882== by 0x7574143: fz_new_icc_colorspace (colorspace.c:458)
==347882== by 0x757313D: fz_new_colorspace_context (colorspace.c:66)
==347882== by 0x7578320: fz_new_context_imp (context.c:222)
==347882== by 0x756DB3C: PyInit__fitz (fitz_wrap.c:35026)
==347882== by 0x680A87: _PyImport_LoadDynamicModuleWithSpec (importdl.c:167)
==347882== by 0x680A87: _imp_create_dynamic_impl.isra.21 (import.c:2302)
==347882== by 0x680A87: _imp_create_dynamic (import.c.h:330)
==347882== by 0x5491D0: cfunction_vectorcall_FASTCALL.lto_priv.1634 (methodobject.c:430)
==347882== by 0x5F9EAD: PyVectorcall_Call (call.c:231)
==347882== by 0x5F9EAD: _PyObject_Call (call.c:266)
==347882==
python: source/fitz/store.c:195: fz_drop_key_storable: Assertion `s->storable.refs != 0' failed.
==347882==
==347882== Process terminating with default action of signal 6 (SIGABRT)
==347882== at 0x4E7CE87: raise (raise.c:51)
==347882== by 0x4E7E7F0: abort (abort.c:79)
==347882== by 0x4E6E3F9: __assert_fail_base (assert.c:92)
==347882== by 0x4E6E471: __assert_fail (assert.c:101)
==347882== by 0x75F9410: fz_drop_key_storable (store.c:195)
==347882== by 0x757387F: fz_drop_colorspace (colorspace.c:293)
==347882== by 0x7573343: fz_drop_colorspace_context (colorspace.c:132)
==347882== by 0x7578064: fz_drop_context (context.c:157)
==347882== by 0x4E81030: __run_exit_handlers (exit.c:108)
==347882== by 0x4E81129: exit (exit.c:139)
==347882== by 0x4E5FC8D: (below main) (libc-start.c:344)
==347882==
==347882== HEAP SUMMARY:
==347882== in use at exit: 3,427,522 bytes in 26,647 blocks
==347882== total heap usage: 115,203 allocs, 88,556 frees, 17,395,912 bytes allocated
==347882==
==347882== LEAK SUMMARY:
==347882== definitely lost: 0 bytes in 0 blocks
==347882== indirectly lost: 0 bytes in 0 blocks
==347882== possibly lost: 3,046,052 bytes in 26,444 blocks
==347882== still reachable: 381,470 bytes in 203 blocks
==347882== suppressed: 0 bytes in 0 blocks
==347882== Rerun with --leak-check=full to see details of leaked memory
==347882==
==347882== For counts of detected and suppressed errors, rerun with: -v
==347882== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5568 from 5)
Your configuration (mandatory)
>>> print(sys.version, "\n", sys.platform, "\n", fitz.__doc__)
3.9.16 (main, Dec 7 2022, 01:11:58)
[GCC 7.5.0]
linux
PyMuPDF 1.21.1: Python bindings for the MuPDF 1.21.1 library.
Version date: 2022-12-13 00:00:01.
Built for Python 3.9 on linux (64-bit).
Tested with PyMuPDF 1.21.1 from wheel, debug build on tag 1.21.1 and on master.