[Bugfix] EntityCollection.__setitem__ skips gridstate resize when replacing entity #261

Closed
opened 2026-03-07 23:19:27 +00:00 by john · 0 comments
Owner

Summary

UIEntityCollection::setitem() (triggered by grid.entities[i] = entity) sets the entity's grid pointer but never initializes or resizes gridstate at all. If the entity had gridstate from a smaller grid, updateVisibility() will write past the end.

Root Cause

UIEntityCollection.cpp:191:

// Replace the element and set grid reference
*it = entity->data;
entity->data->grid = self->grid;

No gridstate initialization or resize happens here — unlike append(), extend(), and insert() which at least have the (buggy) size() == 0 check.

Reproduction

import mcrfpy

small_grid = mcrfpy.Grid(grid_size=(10, 10))
large_grid = mcrfpy.Grid(grid_size=(50, 50))

entity_old = mcrfpy.Entity((5, 5))
entity_new = mcrfpy.Entity((3, 3))

large_grid.entities.append(entity_old)

small_grid.entities.append(entity_new)
entity_new.update_visibility()  # gridstate = 100 entries

large_grid.entities[0] = entity_new  # BUG: no gridstate resize
entity_new.update_visibility()  # heap overflow

Fix

Add gridstate resize after setting the grid reference:

entity->data->grid = self->grid;
if (self->grid) {
    size_t new_size = self->grid->grid_w * self->grid->grid_h;
    if (entity->data->gridstate.size() != new_size) {
        entity->data->gridstate.resize(new_size);
        for (auto& state : entity->data->gridstate) {
            state.visible = false;
            state.discovered = false;
        }
    }
}

Severity

Critical — heap buffer overflow. Worse than append/extend/insert because there's no gridstate handling at all.

## Summary `UIEntityCollection::setitem()` (triggered by `grid.entities[i] = entity`) sets the entity's grid pointer but never initializes or resizes gridstate at all. If the entity had gridstate from a smaller grid, `updateVisibility()` will write past the end. ## Root Cause `UIEntityCollection.cpp:191`: ```cpp // Replace the element and set grid reference *it = entity->data; entity->data->grid = self->grid; ``` No gridstate initialization or resize happens here — unlike `append()`, `extend()`, and `insert()` which at least have the (buggy) `size() == 0` check. ## Reproduction ```python import mcrfpy small_grid = mcrfpy.Grid(grid_size=(10, 10)) large_grid = mcrfpy.Grid(grid_size=(50, 50)) entity_old = mcrfpy.Entity((5, 5)) entity_new = mcrfpy.Entity((3, 3)) large_grid.entities.append(entity_old) small_grid.entities.append(entity_new) entity_new.update_visibility() # gridstate = 100 entries large_grid.entities[0] = entity_new # BUG: no gridstate resize entity_new.update_visibility() # heap overflow ``` ## Fix Add gridstate resize after setting the grid reference: ```cpp entity->data->grid = self->grid; if (self->grid) { size_t new_size = self->grid->grid_w * self->grid->grid_h; if (entity->data->gridstate.size() != new_size) { entity->data->gridstate.resize(new_size); for (auto& state : entity->data->gridstate) { state.visible = false; state.discovered = false; } } } ``` ## Severity **Critical** — heap buffer overflow. Worse than append/extend/insert because there's no gridstate handling at all.
john closed this issue 2026-03-14 06:25:16 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
john/McRogueFace#261
No description provided.