Repository navigation
fix(py): grayscale arrays crash image functions #772
Description
Caution
This issue has been claimed by @Aniketbhil, so it is not recommended that you work on it.
For @Aniketbhil:
If you would like to revoke your claim, comment/untake
Affected languages
- C++
- C
- JavaScript
- Python
- Other
- N/A
If you selected "Other", please specify which language.
No response
Describe the issue
The Python API accepts 2D grayscale NumPy arrays in functions that expect four-channel RGBA input. Passing a grayscale array to invert_image, threshold_image, or black_threshold_image aborts the Python process with heap-corruption-related errors instead of raising a Python exception.
The _inject_dimensions decorator in packages/py/img2num/api.py only checks whether the input has at least two dimensions. It does not validate the channel count.
The affected wrappers in bindings/py/src/img2num_pybind.cpp allocate output arrays using the input shape, while the native implementations in core/src/internal/image_utils.cpp interpret the buffer as RGBA data using ImageLib::RGBA_CONVERTER<uint8_t>.
The Python README documents that images must be four-channel uint8 arrays in RGBA channel order.
I reproduced this with a (64, 64) uint8 NumPy array. invert_image and threshold_image aborted with munmap_chunk(): invalid pointer, while black_threshold_image aborted with double free or corruption (out). Each test ran in a separate process and exited with code 134.
Steps to reproduce
- Build and install the Python package in the project's development environment.
- Run the following Python code:
import numpy as np
import img2num
gray = np.zeros((64, 64), dtype=np.uint8)
img2num.invert_image(gray)
# Aborts with: munmap_chunk(): invalid pointer
img2num.threshold_image(gray, 4)
# Aborts with: munmap_chunk(): invalid pointer
img2num.black_threshold_image(gray, 4)
# Aborts with: double free or corruption (out)- Run each function call in a separate Python process.
- Observe that the process aborts instead of raising a Python exception.
Tested in Python 3.13 on Linux x86_64, using branch repro-3 at revision 565d40ee (upstream/dev, PR #747).
What was the expected result?
Inputs that do not satisfy the documented four-channel uint8 RGBA format should be rejected with a clear Python exception, such as ValueError, before native image processing begins. Valid RGBA inputs should continue to work normally.
Please include some screenshots here if necessary.
The more information we have, the better-equipped we will be to resolve this issue.
No response
Would you like to work on this issue?
Yes
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsIn progress
Activity
Aniketbhil commentedon Oct 15, 2026
/take
Aniketbhil commentedon Oct 18, 2026
I found PR #780, which adds RGBA image shape validation in the Python API and appears to address the crashes reported here.
Since that PR is still open, I'll keep this issue open for now rather than close it prematurely.
Related PR: #780
Ryan-Millard commentedon Oct 18, 2026
Hi @Aniketbhil. Thank you for the issue. This is a known issue in the project and I previously assumed that the documentation would be enough, but that was a bad assumption since not everyone gets to reading the documentation or the documentation may just be bad.
Please would you have a look at #780 and let me know if you think that is the same solution you were considering. We'd really appreciate a review on it since you discovered it and probably know the required fix.
Aniketbhil commentedon Oct 18, 2026
Hi Ryan! Thanks for the context and for asking me to review PR #780.
I inspected the diff, and the new validation requiring an RGBA array with shape (H, W, 4) appears to address the root cause I found. The previous check allowed grayscale and RGB arrays to reach native code that expects RGBA data.
I'll verify the behavior against my original reproductions and check whether the relevant regression tests are covered. I'll share my findings here once I've completed the review.
Aniketbhil commentedon Oct 18, 2026
Hi Ryan! I built PR #780 successfully and tested the changes against my original reproduction cases using the PR's own virtual environment.
Results:
invert_image,threshold_image, andblack_threshold_imageall reject grayscale(64, 64), RGB(64, 64, 3), and single-channel(64, 64, 1)inputs withValueError.(64, 64, 4)inputs and return the expected output shape.All 12 test cases passed. These results confirm that PR #780 fixes the crash scenarios I reported in this issue.
I also noticed that the PR doesn't add dedicated regression tests for these cases. Would it be useful for me to contribute them?