Skip to content

Commit ad5a7b0

Browse files
author
amalxloop
committed
Fix bugs found in security audit: overflow, unchecked malloc, div-by-zero
- sc_gfx_resize (Bug 1): add integer overflow guard before realloc matching the existing check in sc_gfx_init - _sc_font_cache_glyph (Bug 2): reject glyphs wider than atlas (gw > SC_FONT_ATLAS_W) to prevent heap buffer overflow from memcpy past row boundary - Vulkan backend (Bug 4): add NULL checks for all 6 unchecked malloc/calloc calls (fmt list, swapchain arrays, phys array, queue family props) — return VK_ERROR_OUT_OF_HOST_MEMORY or SC_ERR_OOM on failure - Layout SPACE_AROUND (Bug 6): add nc_in/nc > 0 guard to prevent division by zero in both single-line and multi-line paths - sc_font.h: document ASCII-only limitation (UTF-8 not decoded)
1 parent 1369482 commit ad5a7b0

4 files changed

Lines changed: 22 additions & 2 deletions

File tree

backends/sc_backend_vulkan.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ static VkResult _sc_vk_create_swapchain(VkDevice dev, VkPhysicalDevice phy,
417417
u32 fmt_count;
418418
vkGetPhysicalDeviceSurfaceFormatsKHR(phy, surface, &fmt_count, NULL);
419419
VkSurfaceFormatKHR *fmts = (VkSurfaceFormatKHR*)malloc(fmt_count * sizeof(VkSurfaceFormatKHR));
420+
if (!fmts) return VK_ERROR_OUT_OF_HOST_MEMORY;
420421
vkGetPhysicalDeviceSurfaceFormatsKHR(phy, surface, &fmt_count, fmts);
421422

422423
VkSurfaceFormatKHR sf = fmts[0];
@@ -454,6 +455,13 @@ static VkResult _sc_vk_create_swapchain(VkDevice dev, VkPhysicalDevice phy,
454455
*out_images = (VkImage*)malloc(*out_len * sizeof(VkImage));
455456
*out_views = (VkImageView*)malloc(*out_len * sizeof(VkImageView));
456457
*out_fbos = (VkFramebuffer*)malloc(*out_len * sizeof(VkFramebuffer));
458+
if (!*out_images || !*out_views || !*out_fbos) {
459+
free(*out_images); free(*out_views); free(*out_fbos);
460+
*out_images = NULL; *out_views = NULL; *out_fbos = NULL;
461+
vkDestroySwapchainKHR(dev, *out_swap, NULL);
462+
*out_swap = VK_NULL_HANDLE; *out_len = 0;
463+
return VK_ERROR_OUT_OF_HOST_MEMORY;
464+
}
457465
vkGetSwapchainImagesKHR(dev, *out_swap, out_len, *out_images);
458466

459467
for (u32 i = 0; i < *out_len; i++) {
@@ -731,6 +739,7 @@ SCResult sc_vulkan_init(SCGfxContext *ctx, const SCGfxDesc *desc,
731739
vkEnumeratePhysicalDevices(s->instance, &phy_count, NULL);
732740
if (phy_count == 0) { sc_vulkan_shutdown(ctx); return SC_ERR_GFX; }
733741
VkPhysicalDevice *phys = (VkPhysicalDevice*)malloc(phy_count * sizeof(VkPhysicalDevice));
742+
if (!phys) { sc_vulkan_shutdown(ctx); return SC_ERR_OOM; }
734743
vkEnumeratePhysicalDevices(s->instance, &phy_count, phys);
735744
s->phy_dev = phys[0];
736745
for (u32 i = 0; i < phy_count; i++) {
@@ -747,6 +756,7 @@ SCResult sc_vulkan_init(SCGfxContext *ctx, const SCGfxDesc *desc,
747756
vkGetPhysicalDeviceQueueFamilyProperties(s->phy_dev, &qf_count, NULL);
748757
VkQueueFamilyProperties *qf = (VkQueueFamilyProperties*)malloc(
749758
qf_count * sizeof(VkQueueFamilyProperties));
759+
if (!qf) { sc_vulkan_shutdown(ctx); return SC_ERR_OOM; }
750760
vkGetPhysicalDeviceQueueFamilyProperties(s->phy_dev, &qf_count, qf);
751761

752762
u32 gfx_idx = UINT32_MAX;

include/sc_font.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
* Each SCFont represents one font face at a specific pixel size.
66
* Glyphs are lazily rendered and cached in a packed atlas texture.
77
*
8+
* NOTE: Only ASCII (U+0000–U+007F) is supported for text rendering.
9+
* Multi-byte UTF-8 sequences are not decoded.
10+
*
811
* #define SC_FONT_IMPLEMENTATION
912
* #include "sc_font.h"
1013
*/
@@ -97,6 +100,12 @@ static SCFontGlyph *_sc_font_cache_glyph(SCFont *font, u32 codepoint) {
97100
return g;
98101
}
99102

103+
/* Reject glyph wider than the atlas (would overflow row) */
104+
if ((u32)gw > SC_FONT_ATLAS_W) {
105+
stbtt_FreeBitmap(bitmap, NULL);
106+
return NULL;
107+
}
108+
100109
/* Pack into atlas (simple row-based packer) */
101110
if (font->atlas_cursor_x + (u32)gw > SC_FONT_ATLAS_W) {
102111
font->atlas_cursor_x = 0;

include/sc_gfx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ void sc_gfx_set_rasterize(SCGfxContext *ctx, bool enable) {
692692

693693
SCResult sc_gfx_resize(SCGfxContext *ctx, u32 width, u32 height) {
694694
if (!ctx || width == 0 || height == 0) return SC_ERR_INVALID_ARG;
695+
if (height > (SIZE_MAX / 4) / width) return SC_ERR_INVALID_ARG;
695696
#ifdef SC_GFX_BACKEND_VULKAN
696697
if (ctx->backend == SC_BACKEND_VULKAN) {
697698
return sc_vulkan_resize(ctx, width, height);

include/sc_layout.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ static void _sc_layout_distribute(SCLayoutTree *t, i32 idx,
381381
case SC_JUSTIFY_SPACE_BETWEEN: cursor = pad_start_main;
382382
igap = (nc_in > 1) ? line_free / (f32)(nc_in - 1) : 0;
383383
igap += s->gap; break;
384-
case SC_JUSTIFY_SPACE_AROUND: igap = line_free / (f32)nc_in;
384+
case SC_JUSTIFY_SPACE_AROUND: igap = (nc_in > 0) ? line_free / (f32)nc_in : 0;
385385
cursor = pad_start_main + igap * 0.5f; igap += s->gap; break;
386386
}
387387

@@ -454,7 +454,7 @@ static void _sc_layout_distribute(SCLayoutTree *t, i32 idx,
454454
case SC_JUSTIFY_SPACE_BETWEEN: cursor = pad_start_main;
455455
igap = (nc > 1) ? free_space / (f32)(nc-1) : 0;
456456
igap += s->gap; break;
457-
case SC_JUSTIFY_SPACE_AROUND: igap = free_space / (f32)nc;
457+
case SC_JUSTIFY_SPACE_AROUND: igap = (nc > 0) ? free_space / (f32)nc : 0;
458458
cursor = pad_start_main + igap*0.5f; igap += s->gap; break;
459459
}
460460

0 commit comments

Comments
 (0)