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

realloc fails if extending block in-place crosses the address 0xffff #922

Open
redshx86 opened this issue Jul 14, 2023 · 8 comments
Open
Labels
bug Something isn't working

Comments

@redshx86
Copy link

redshx86 commented Jul 14, 2023

Check at libc/stdlib/realloc.c#60 causes call to fail if extending block to the new size causes pointer overflow, even if there's plenty of free memory to move data. Instead of returning NULL it should jump to the line 146

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 14, 2023

Hmm, I'm afraid when I wrote malloc I never even remotely considered that devices might have more than 64 KiB of memory …

@redshx86
Copy link
Author

Well, external SRAM supported since ATmega103, the very first AVRmega chip. Although using external SRAM isn't exactly common i guess, but if you use it you probably want full 64K because why not.

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 14, 2023

Nevertheless, you couldn't address more than 64 KiB of RAM on the ATmega103/128 etc., RAM addresses have only been 16 bits (and part of the external RAM was unusable since it's shadowed by IO registers and internal RAM).
It was only with Xmega that larger data pointers were made possible, but by that time, malloc was already like 10 years old.
I'l see whether there's an appropriate fix.

@redshx86
Copy link
Author

Umm it doesn't need to be more than 64K of RAM. Call fails each time when block + size_new > 0xffff for example if trying to extend 0x100-byte block at 0xfe80 to 0x200 bytes, realloc fails because 0xfe80+0x200 > 0xffff, even if there's tons of free RAM. I made a workaround for my code by trying malloc if realloc fails but it took some time to figure out because allocator issue wasn't exactly the first thing to suspect :)

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 14, 2023

But if your pointer is already at 0xfe80, and you try extending it by 0x200, your region ends up beyond the area that can be addressed by a usual 16-bit pointer, so what's the point? Somehow, I don't get it … to me, that only makes sense if your system can actually address more than 64 KiB – and I am still under the assumption that AVR-GCC could not handle data addresses wider than 16 bits.

@redshx86
Copy link
Author

redshx86 commented Jul 14, 2023

Block (ptr=0xfe80,size=0x100) is a vaild allocated block for 64K memory space. Trying to extend it to size=0x200 without moving of course isn't possible because it crosses the address space end. So valid realloc behavior in this case would be to move data somewhere if there's some space available and return pointer to the new allocated block, not fail immediately. So i guess if wrap detected at line 60 i think it should jump to malloc at line 146 not return NULL

@dl8dtl
Copy link
Contributor

dl8dtl commented Jul 14, 2023

Ah, now I got it. :-) Thanks for keeping explaing it to me.

@dl8dtl dl8dtl added the bug Something isn't working label Jul 14, 2023
@sprintersb
Copy link
Collaborator

sprintersb commented Aug 1, 2023

and I am still under the assumption that AVR-GCC could not handle data addresses wider than 16 bits.

ACK. Some AVRs feature RAMPX/Y/Z/D registers to extend X/Y/Z resp. LDS/STS to 24-bit pointers. But avr-gcc does not support segmented memory like that. Or more correct, RAM pointers are always 16 bits wide, and supporting such RAM would require a default pointer size of 24 bits and thus a considerable re-write of avr-gcc. llvm is no different in that regard.

One could support (parts of) upper RAM by means of special address spaces similar to __memx, but it would be PITA and you won't find anyone willing to implement that.

That said, the only way to make use of this is by means of dedicated hacks / asm code, e.g. to make use of upprt RAM for some buffer that's managed "by hand".

The only "support" for RAMP* is that avr-gcc saves / restores them when they might be clobbered in an ISR.

The current issue seems to be that AVR-LibC doesn't handle memory segmentation well, i.e. even though there is enough memory in priciple, realloc fails.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants