Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add mutt_mem_recalloc() #3890

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft

add mutt_mem_recalloc() #3890

wants to merge 5 commits into from

Conversation

flatcap
Copy link
Member

@flatcap flatcap commented Jun 12, 2023

Add a function to resize a block of memory.
If the size increases, then zero the new bit.

Discussion

There are about 90 calls to mutt_mem_realloc() in the code.
They fall into four categories:

  • Structured ('n' repeated blocks)
    A dynamic array of objects / pointers

  • Unstructured (one large undifferentiated block)

  • Wipe
    The new memory is memset(0)d, or zeroed with a for loop

  • No wipe
    New memory is left uninitialised

Should we always zero the new block?

For a small cost, should we initialise all memory?
Even if it's going to get overwritten soon?

Should we replace any malloc()s with calloc() and recalloc()?

Is recalloc() a worthwhile step forward?

I worked through a handful of functions which dynamically allocate arrays.
They would be tidier using recalloc(), but ultimately they'd probably be better off using ARRAY.
Upgrading to ARRAY would be quite a bit of work.

Add recalloc()

Ages ago, on IRC, we discussed a recalloc() function that would streamline realloc()/memset()

Here's what it could look like...

void mutt_mem_recalloc(void *ptr, size_t cur_size, size_t new_size)

Before recalloc()

  • Calculate the new size
  • Reallocate the memory
  • Wipe the new bit

neomutt/editor/state.c

Lines 62 to 67 in 371a8ad

num = ROUND_UP(num + 4, 128);
mutt_mem_realloc(&es->wbuf, num * sizeof(wchar_t));
memset(es->wbuf + es->wbuflen, 0, (num - es->wbuflen) * sizeof(wchar_t));
es->wbuflen = num;

After recalloc()

neomutt/editor/state.c

Lines 61 to 66 in becd9a0

num = ROUND_UP(num + 4, 128);
const size_t cur_size = es->wbuflen * sizeof(wchar_t);
const size_t new_size = num * sizeof(wchar_t);
mutt_mem_recalloc(&es->wbuf, cur_size, new_size);
es->wbuflen = num;

The code usually stores the number of items contained in the array,
so for tidiness I've done the calculations first.

It's a bit better, but still a bit clunky.

Add recallocarray()

mutt_mem_recalloc(ptr, cur_num * block_size, new_num * block_size);

This is just a convenience wrapper around recalloc() -- it simplifies the maths.

After recallocarray()

neomutt/editor/state.c

Lines 61 to 64 in a7f7cf1

num = ROUND_UP(num + 4, 128);
mutt_mem_recallocarray(&es->wbuf, es->wbuflen, num, sizeof(wchar_t));
es->wbuflen = num;

@flatcap flatcap added type:discuss Your views/opinions are requested topic:refactoring Code refactoring labels Jun 12, 2023
@flatcap flatcap requested a review from a team as a code owner June 12, 2023 01:02
@flatcap flatcap self-assigned this Jun 12, 2023
@flatcap flatcap marked this pull request as draft June 12, 2023 01:02
@vuori
Copy link
Contributor

vuori commented Jun 18, 2023

I think this is a good idea. Zeroing memory will either prevent UAFs (null pointer is detected) or cause a more consistent and easier to debug crash.

@flatcap flatcap force-pushed the devel/realloc branch 3 times, most recently from 1176268 to d8d5c4c Compare January 27, 2024 01:04
@flatcap flatcap force-pushed the devel/realloc branch 3 times, most recently from fd9637a to 6005578 Compare March 29, 2024 01:43
@flatcap flatcap force-pushed the devel/realloc branch 2 times, most recently from c4049d2 to 428e780 Compare April 5, 2024 11:13
@flatcap flatcap force-pushed the devel/realloc branch 2 times, most recently from c25bb45 to ec3743c Compare May 8, 2024 20:10
Reallocate a block of memory.
If the size increases, automatically zero the new bit.
Add a calloc()-style wrapper around recalloc().
@flatcap flatcap changed the title add mutt_mem_realloc_zero() add mutt_mem_recalloc() May 9, 2024
@flatcap
Copy link
Member Author

flatcap commented May 9, 2024

Update: Renamed functions -- Prior art in BSD.
Thanks, @alejandro-colomar.

@alejandro-colomar
Copy link
Member

alejandro-colomar commented May 9, 2024

Update: Renamed functions -- Prior art in BSD. Thanks, @alejandro-colomar.

Ahhh, I didn't find this PR! :-)

@alejandro-colomar
Copy link
Member

Hi @flatcap !

Sorry; I just remembered a detail about recallocarray(3): not only it clears new memory, it also clears the freed memory (like explicit_bzero(3)).

Maybe we should also clear the freed space if new_size < cur_size?

Or if we don't care about that, use a slightly different name such as rezalloc()?

@flatcap
Copy link
Member Author

flatcap commented May 9, 2024

Maybe we should also clear the freed space if new_size < cur_size?

Hmm... I hadn't considered that.
I can't actually think of any cases that we shrink an array; they tend to get nuked and rebuilt.
Probably worth doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic:refactoring Code refactoring type:discuss Your views/opinions are requested
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants