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

memory: fix memory alignment for dynamic allocation #20489

Merged
merged 2 commits into from Oct 31, 2022

Conversation

jpalus
Copy link
Contributor

@jpalus jpalus commented Oct 4, 2022

all pointers returned by arena_alloc residing in arena block should be properly aligned

also make ARENA_ALIGN reflect what glibc does (with MALLOC_ALIGNMENT) to have proper alignment for each platform. might not be fully accurate but it's best effort approach keeping c99 compatibility. with c11 it could be reduced to single:

#define ARENA_ALIGN _Alignof(max_align_t)

Fixes #20437

@zeertzjq zeertzjq requested a review from bfredl October 4, 2022 22:54
@zeertzjq zeertzjq added this to the 0.8.1 milestone Oct 5, 2022
@zeertzjq
Copy link
Member

zeertzjq commented Oct 5, 2022

lint failure

Comment on lines 50 to 53
# define ARENA_ALIGN 16
# else
# define ARENA_ALIGN ((2 * sizeof(size_t)) < \
__alignof__(long double) ? __alignof__(long double) : (2 * sizeof(size_t)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a source that the recommended alignment on x86 is 16 and not 8? and that the required one on AARCH64 is 16 and not 8? (it can be assumed we never use weird or obsolete x87 doubles, nor 128 bit ints). just hardcoding ARENA_ALIGN to MAX(sizeof(void *), sizeof(double)) would have be been simpler.

Also __GNUC__ looks fishy. we only care what the CPU wants, not about gcc/glibc's ideas.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above logic is based purely on:
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/generic/malloc-alignment.h;h=ef0f381f772088d3e8a8648410bba85b1a970451;hb=c804cd1c00adde061ca51711f63068c103e94eef
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/generic/malloc-alignment.h;h=ef0f381f772088d3e8a8648410bba85b1a970451;hb=c804cd1c00adde061ca51711f63068c103e94eef

just hardcoding ARENA_ALIGN to MAX(sizeof(void *), sizeof(double)) would have be been simpler.

I don't really know what are neovim's alignment requirements hence PR attempts to be as generic as possible. If you're sure it will never reach maximum then I guess it's fine.

Also __GNUC__ looks fishy. we only care what the CPU wants, not about gcc/glibc's ideas.

__GNUC__ is there to make sure __i386__ and __alignof__ are available.

Copy link
Member

@bfredl bfredl Oct 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, we should try to just do MAX(sizeof(double), sizeof(void *)) here without any GNU-specific checks. the only issue I can see is that we use 4-byte alignment on ARMv7 where 8-byte is needed, due to 64-bit floats. if there is still an issue even with that people can report a new issue.

Comment on lines 606 to 599
if (arena_align_offset(arena->cur_blk + arena->pos, ARENA_ALIGN, &align_pos) < 0) {
alignment_ok = false;
}
}
if (arena->pos + size > arena->size || !arena->cur_blk) {
if (size > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) >> 1) {
if (arena->pos + align_pos + size > arena->size || !alignment_ok) {
if (size + (align ? (ARENA_ALIGN - 1) : 0) > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk))
>> 1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks needlessly complicated. Expressing the constraint and doing overflow checking direct in arena->pos integer space was much simpler (instead of first converting to pointer so we can play-pretend "secure pointer handling" by then converting back to uintptr to do pointer-space overflow check.). Remember, this is an interface for known internal consumers, not a malloc implementation which needs be c-standard paranoia compliant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear you'd like to drop "fix(memory): check for uintptr_t overflow" correct?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ye, that looks like it.

@jpalus
Copy link
Contributor Author

jpalus commented Oct 6, 2022

Commit with overflow reverted and ARENA_ALIGN changed to MAX(sizeof(void *), sizeof(double)). If ok I will squash the commits.

@zeertzjq
Copy link
Member

zeertzjq commented Oct 7, 2022

Needs a rebase

@jpalus
Copy link
Contributor Author

jpalus commented Oct 7, 2022

Rebased and squashed.

all pointers returned by arena_alloc residing in arena block should be
properly aligned

to meet neovim's alignment requirements but keeping it simple settle on
ARENA_ALIGN = MAX(sizeof(void *), sizeof(double)).
@bfredl bfredl force-pushed the memory-alignment branch 3 times, most recently from 02d85f3 to 8b7247a Compare October 31, 2022 10:12
In particular, we can assume the xmalloc-ed pointer is at least
double-aligned, otherwise nothing work work.
@bfredl bfredl merged commit bf3cbee into neovim:master Oct 31, 2022
@github-actions github-actions bot removed the request for review from bfredl October 31, 2022 16:10
pld-gitsync pushed a commit to pld-linux/neovim that referenced this pull request Nov 17, 2022
- fix memory alignment crash on armv7
  (neovim/neovim#20489)
@polyzen
Copy link

polyzen commented Nov 19, 2022

For some reason this didn't make it into 0.8.1.

@lewis6991
Copy link
Member

That's a shame, maybe we should consider releasing 0.8.2

@clason
Copy link
Member

clason commented Nov 19, 2022

This is the plan, unless 0.9 gets finished first.

@github-actions
Copy link
Contributor

Successfully created backport PR #21127 for release-0.8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

armv7 crash
6 participants