-
-
Notifications
You must be signed in to change notification settings - Fork 212
Fix no palette 8 bit surface gfxdraw segfault #3627
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughThis pull request fixes segfaults in gfxdraw functions when operating on 8-bit surfaces without palettes. The fix replaces direct palette access in Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
test/gfxdraw_test.py (1)
875-913: Good regression test for no-palette segfault fix.The test correctly creates an 8-bit surface without a palette (matching the issue #586 reproduction case) and verifies that all gfxdraw functions can be called without crashing. The comprehensive list of 18 functions tested is excellent coverage.
The bare
except Exception(line 912) is flagged by static analysis, but for a regression test focused on preventing segfaults, this approach is acceptable since any exception is re-raised with context viaself.fail(). However, if you want to be more specific, you could catch only the expected exception types or use a more targeted approach.Note: This test validates that the functions don't crash, but doesn't verify the visual output is correct on no-palette surfaces.
If you'd like to make the exception handling more specific, consider:
try: func = getattr(pygame.gfxdraw, name) func(*args) except (SystemError, MemoryError, AttributeError) as e: self.fail(f"gfxdraw.{name} raised an exception: {e}")This would catch segfault-related errors while allowing other exceptions to propagate normally for debugging.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src_c/SDL_gfx/SDL_gfxPrimitives.c(2 hunks)test/gfxdraw_test.py(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: Starbuck5
Repo: pygame-community/pygame-ce PR: 3573
File: src_c/_pygame.h:108-133
Timestamp: 2025-09-01T20:18:57.500Z
Learning: In pygame-ce PR #3573, PG_SURF_BitsPerPixel was changed from a simple macro to a static inline function to handle SDL2/SDL3 differences. SDL2's BitsPerPixel includes padding bits (e.g., RGBX => 32) while SDL3's SDL_BITSPERPIXEL excludes padding (e.g., RGBX => 24). The new implementation bridges this gap rather than removing the helper entirely.
Learnt from: Starbuck5
Repo: pygame-community/pygame-ce PR: 3573
File: src_c/_pygame.h:115-126
Timestamp: 2025-09-01T20:22:31.010Z
Learning: In pygame-ce PR #3573, the PG_SURF_BitsPerPixel function implementation uses hardcoded return values of 32 for YUY2/UYVY/YVYU FOURCC formats because it's copying the exact logic from SDL's internal SDL_GetMasksForPixelFormat function. This ensures perfect compatibility between SDL2 and SDL3 behaviors rather than using the technically more accurate values that might be returned by SDL_GetPixelFormatDetails.
📚 Learning: 2025-09-01T20:18:57.500Z
Learnt from: Starbuck5
Repo: pygame-community/pygame-ce PR: 3573
File: src_c/_pygame.h:108-133
Timestamp: 2025-09-01T20:18:57.500Z
Learning: In pygame-ce PR #3573, PG_SURF_BitsPerPixel was changed from a simple macro to a static inline function to handle SDL2/SDL3 differences. SDL2's BitsPerPixel includes padding bits (e.g., RGBX => 32) while SDL3's SDL_BITSPERPIXEL excludes padding (e.g., RGBX => 24). The new implementation bridges this gap rather than removing the helper entirely.
Applied to files:
src_c/SDL_gfx/SDL_gfxPrimitives.c
📚 Learning: 2025-09-01T20:22:31.010Z
Learnt from: Starbuck5
Repo: pygame-community/pygame-ce PR: 3573
File: src_c/_pygame.h:115-126
Timestamp: 2025-09-01T20:22:31.010Z
Learning: In pygame-ce PR #3573, the PG_SURF_BitsPerPixel function implementation uses hardcoded return values of 32 for YUY2/UYVY/YVYU FOURCC formats because it's copying the exact logic from SDL's internal SDL_GetMasksForPixelFormat function. This ensures perfect compatibility between SDL2 and SDL3 behaviors rather than using the technically more accurate values that might be returned by SDL_GetPixelFormatDetails.
Applied to files:
src_c/SDL_gfx/SDL_gfxPrimitives.c
🧬 Code graph analysis (1)
test/gfxdraw_test.py (2)
buildconfig/stubs/pygame/rect.pyi (1)
Rect(307-307)src_c/gfxdraw.c (1)
gfxdraw(1046-1079)
🪛 Ruff (0.14.2)
test/gfxdraw_test.py
912-912: Do not catch blind exception: Exception
(BLE001)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
- GitHub Check: build (ubuntu-22.04)
- GitHub Check: msys2 (mingw64, x86_64)
- GitHub Check: msys2 (ucrt64, ucrt-x86_64)
- GitHub Check: aarch64
- GitHub Check: i686
- GitHub Check: x86_64
- GitHub Check: debug_coverage (ubuntu-24.04, 3.14.0rc1)
- GitHub Check: debug_coverage (ubuntu-24.04, 3.9.23)
- GitHub Check: debug_coverage (ubuntu-24.04, 3.13.5)
- GitHub Check: Debian (Bookworm - 12) [armv7]
- GitHub Check: Pyodide build
- GitHub Check: build (macos-14)
- GitHub Check: Debian (Bookworm - 12) [armv6]
- GitHub Check: Debian (Bookworm - 12) [s390x]
- GitHub Check: Debian (Bookworm - 12) [ppc64le]
- GitHub Check: build (ubuntu-24.04)
- GitHub Check: AMD64
- GitHub Check: dev-check
- GitHub Check: x86
🔇 Additional comments (2)
src_c/SDL_gfx/SDL_gfxPrimitives.c (2)
296-308: LGTM - Correct fix for no-palette 8-bit surfaces.The change correctly addresses the segfault by using
SDL_GetRGBto extract color components instead of directly accessing the palette. The approach:
- Works for both palette and non-palette 8-bit surfaces
- Performs proper alpha blending on RGB components
- Uses
SDL_MapRGBto convert back to the surface formatThe alpha blending math is correct and the fix is minimal.
603-619: LGTM - Consistent fix for filled rectangle alpha blending.This change applies the same SDL_GetRGB approach to fix the segfault in filled rectangle drawing. Good optimization to extract the source color RGB components once outside the loop (line 606) while extracting destination pixel RGB per iteration (line 613).
Fixes #586
Yes, gfxdraw is scheduled for eventual removal and is generally unmaintained, but we should still not segfault.