Skip to content

fix(mem): typo = instead of - corrupted initial heap block size!! - #102

Merged
im-nymii merged 4 commits into
Auri-OS:developfrom
kudasaixc:patch-1
Jul 3, 2026
Merged

fix(mem): typo = instead of - corrupted initial heap block size!!#102
im-nymii merged 4 commits into
Auri-OS:developfrom
kudasaixc:patch-1

Conversation

@kudasaixc

Copy link
Copy Markdown
Contributor

In memory_init(), line 46 assigns heap_end = HEAP_VIRT_START instead of subtracting, due to a =/- typo. This makes the first free block claim a size of ~3.2 GB (0xCFFFFFF0), so any large malloc returns pointers into unmapped virtual memory (page fault on write). It also resets heap_end to the heap start, so heap_grow() would remap fresh physical frames over existing blocks, corrupting the heap and leaking PMM frames.

In memory_init(), line 46 assigns heap_end = HEAP_VIRT_START instead of subtracting, due to a =/- typo. This makes the first free block claim a size of ~3.2 GB (0xCFFFFFF0), so any large malloc returns pointers into unmapped virtual memory (page fault on write). It also resets heap_end to the heap start, so heap_grow() would remap fresh physical frames over existing blocks, corrupting the heap and leaking PMM frames.
@im-nymii

im-nymii commented Jul 3, 2026

Copy link
Copy Markdown
Member

LGTM, add yourself as a contributor in the README file !

@im-nymii
im-nymii merged commit 2902006 into Auri-OS:develop Jul 3, 2026
3 checks passed
@kudasaixc

kudasaixc commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

How it triggers, with the typo memory_init runs:

head->size = (heap_end = HEAP_VIRT_START) - HEADER_SIZE;

so the free list advertises a single block of 0xD0000000 - 16 = 0xCFFFFFF0 (about 3.2 GB) while only HEAP_INITIAL_PAGES (16 x 4 KB = 64 KB) are actually mapped. It also resets heap_end back to HEAP_VIRT_START.

Any allocation bigger than the 64 KB that is really mapped is handed out without growing the heap, because malloc thinks the first block is huge:

char *p = malloc(0x20000);   // 128 KB, "fits" in the fake 3.2 GB block
memset(p, 0x41, 0x20000);    // writes past the 64 KB that is mapped

The memset walks off the end of the mapped region and faults at the first unmapped page (around 0xD0010000). And since heap_end was reset to the heap start, the next heap_grow re-maps fresh physical frames on top of the existing blocks, so even correctly sized allocations start corrupting each other and leak PMM frames.

Fix: head->size = (heap_end - HEAP_VIRT_START) - HEADER_SIZE; so the block advertises the real 64 KB minus the header.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

2 participants