Skip to content

Commit faef6d4

Browse files
authored
Fix segfault with antialiased draw functions with a depth different than 32bits (#3008)
* fix segfault * format fix * format issue * another format issue * f issue * add tests * py format fix * removed 24bits case * removed masks * format fix * fix segfault & antialiasing for 24bits * format issue * format issue 2 * format issue 3 * switch refactor * clang format * draw.c skill issue * test update * refactor * 8bit fix * format issue * big endian fix * switch case * hopefully it fixes some problems * removed not necessary include * SDL3 compatibility * size_t to int
1 parent c0d17a4 commit faef6d4

File tree

2 files changed

+74
-2
lines changed

2 files changed

+74
-2
lines changed

src_c/draw.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,15 +1126,42 @@ get_antialiased_color(SDL_Surface *surf, int x, int y, Uint32 original_color,
11261126
float brightness)
11271127
{
11281128
Uint8 color_part[4], background_color[4];
1129-
Uint32 *pixels = (Uint32 *)surf->pixels;
11301129
SDL_GetRGBA(original_color, surf->format, &color_part[0], &color_part[1],
11311130
&color_part[2], &color_part[3]);
11321131
if (x < surf->clip_rect.x || x >= surf->clip_rect.x + surf->clip_rect.w ||
11331132
y < surf->clip_rect.y || y >= surf->clip_rect.y + surf->clip_rect.h)
11341133
return original_color;
1135-
SDL_GetRGBA(pixels[(y * surf->w) + x], surf->format, &background_color[0],
1134+
1135+
Uint32 pixel = 0;
1136+
int bpp = PG_SURF_BytesPerPixel(surf);
1137+
Uint8 *pixels = (Uint8 *)surf->pixels + y * surf->pitch + x * bpp;
1138+
1139+
switch (bpp) {
1140+
case 1:
1141+
pixel = *pixels;
1142+
break;
1143+
1144+
case 2:
1145+
pixel = *((Uint16 *)pixels);
1146+
break;
1147+
1148+
case 3:
1149+
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
1150+
pixel = (pixels[0]) + (pixels[1] << 8) + (pixels[2] << 16);
1151+
#else /* SDL_BIG_ENDIAN */
1152+
pixel = (pixels[2]) + (pixels[1] << 8) + (pixels[0] << 16);
1153+
#endif /* SDL_BIG_ENDIAN */
1154+
break;
1155+
1156+
default: /* case 4: */
1157+
pixel = *((Uint32 *)pixels);
1158+
break;
1159+
}
1160+
1161+
SDL_GetRGBA(pixel, surf->format, &background_color[0],
11361162
&background_color[1], &background_color[2],
11371163
&background_color[3]);
1164+
11381165
color_part[0] = (Uint8)(brightness * color_part[0] +
11391166
(1 - brightness) * background_color[0]);
11401167
color_part[1] = (Uint8)(brightness * color_part[1] +

test/draw_test.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7176,6 +7176,51 @@ def test_color_validation(self):
71767176
with self.assertRaises(TypeError):
71777177
draw.polygon(surf, col, points, 0)
71787178

7179+
def test_aafunctions_depth_segfault(self):
7180+
"""Ensure future commits don't break the segfault fixed by pull request
7181+
https://github.com/pygame-community/pygame-ce/pull/3008
7182+
"""
7183+
7184+
pixels_to_check = [(160, 102), (499, 300), (320, 258), (192, 252)]
7185+
pixel_colors_8 = [
7186+
pygame.Color(0, 182, 0, 255),
7187+
pygame.Color(0, 0, 170, 255),
7188+
pygame.Color(255, 0, 0, 255),
7189+
pygame.Color(255, 0, 0, 255),
7190+
]
7191+
7192+
pixel_colors_16 = [
7193+
pygame.Color(0, 178, 0, 255),
7194+
pygame.Color(0, 0, 213, 255),
7195+
pygame.Color(246, 0, 0, 255),
7196+
pygame.Color(222, 0, 0, 255),
7197+
]
7198+
7199+
pixel_colors_24_32 = [
7200+
pygame.Color(0, 178, 0, 255),
7201+
pygame.Color(0, 0, 209, 255),
7202+
pygame.Color(247, 0, 0, 255),
7203+
pygame.Color(223, 0, 0, 255),
7204+
]
7205+
7206+
for depth in (8, 16, 24, 32):
7207+
# all values must stay so to reproduce the segfault
7208+
surf = pygame.Surface(size=(512, 512), flags=0, depth=depth)
7209+
7210+
draw.aacircle(surf, pygame.Color("red"), (256, 256), 64)
7211+
draw.aaline(surf, pygame.Color("blue"), (256, 256), (500, 300))
7212+
draw.aalines(
7213+
surf, pygame.Color("green"), False, [(100, 100), (100, 500), (160, 100)]
7214+
)
7215+
7216+
for i, pixel in enumerate(pixels_to_check):
7217+
if depth == 8:
7218+
self.assertEqual(surf.get_at(pixel), pixel_colors_8[i])
7219+
elif depth == 16:
7220+
self.assertEqual(surf.get_at(pixel), pixel_colors_16[i])
7221+
else:
7222+
self.assertEqual(surf.get_at(pixel), pixel_colors_24_32[i])
7223+
71797224

71807225
###############################################################################
71817226

0 commit comments

Comments
 (0)