worksheet: fix quadratic over-allocation in _set_default_table_columns

_set_default_table_columns iterated num_cols times and called
calloc(num_cols, sizeof(lxw_table_column)) each time, allocating
num_cols structs per slot when only one is needed.  Total allocation
grew as num_cols^2 instead of num_cols.

For a table at Excel's 16,384-column limit this would require roughly
16,384 * (16,384 * sizeof(lxw_table_column)) bytes -- well over 10 GB --
causing calloc to fail with LXW_ERROR_MEMORY_MALLOC_FAILED on any
ordinary system.

NOTE: a direct regression test for this at the Excel column maximum
would require allocating more than 6 GB before the fix and is therefore
not included in the test suite.  Existing table tests cover correctness
for small column counts; those tests continue to pass because the cleanup
code freed the over-allocated blocks via free(columns[i]), so there was
no leak or double-free.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Bill Denney 2026-04-05 18:36:13 +00:00
parent 88a44a9ffa
commit eeb2d89c14

View file

@ -1689,7 +1689,7 @@ _set_default_table_columns(lxw_table_obj *table_obj)
for (i = 0; i < num_cols; i++) {
lxw_snprintf(col_name, LXW_ATTR_32, "Column%d", i + 1);
column = calloc(num_cols, sizeof(lxw_table_column));
column = calloc(1, sizeof(lxw_table_column));
RETURN_ON_MEM_ERROR(column, LXW_ERROR_MEMORY_MALLOC_FAILED);
header = lxw_strdup(col_name);