Commit Graph

6724 Commits

Author SHA1 Message Date
Feoramund efba9a1fb7 Disable usage of AddressSanitizer pending a per-allocator review
It has been discovered that AddressSanitizer does not keep a 1:1 mapping
of which bytes are poisoned and which are not. This can cause issues for
allocations less than 8 bytes and where addresses straddle 8-byte
boundaries.

See the following link for more information:

https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm#mapping
2025-06-15 15:06:28 -04:00
Feoramund 134c39b58b mem: Standardize panic messages 2025-06-15 12:34:16 -04:00
Feoramund e4258b151e mem: Review all documentation comments 2025-06-15 12:34:16 -04:00
Feoramund 7524762620 mem: Poison memory for Buddy_Allocator 2025-06-15 12:34:16 -04:00
Feoramund 7e77bd425f mem: Guard against size 0 in dynamic_arena_resize_* 2025-06-15 12:34:16 -04:00
Feoramund 78a10b462f mem: Poison memory for Dynamic_Arena 2025-06-15 12:34:16 -04:00
Feoramund de3c322899 mem: Make dynamic_arena_alloc not private
None of the other `*_alloc` procs are private, and this proc is even
referenced in public documentation comments.
2025-06-15 12:34:16 -04:00
Feoramund 652c0c997d mem: Remove bogus comments
There is no `dynamic_arena_free`; the mode is not implemented
2025-06-15 12:34:15 -04:00
Feoramund c1e3171178 mem: Remove comment about calling panic
The behavior is codified in the comment as returning `Invalid_Pointer`.
2025-06-15 12:34:15 -04:00
Feoramund aaeae8bc7d mem: Remove trailing whitespace 2025-06-15 12:34:15 -04:00
Feoramund 47a54dd11a mem: Panic when passing invalid pointers to small stack free/resize
This is consistent with `Stack_Allocator`.
2025-06-15 12:34:15 -04:00
Feoramund 3261896790 mem: Correct wrong error message 2025-06-15 12:34:15 -04:00
Feoramund aa41a77fc4 mem: Check if alignment matches on Small_Stack resize 2025-06-15 12:34:15 -04:00
Feoramund 3a02918efc mem: Make small_stack_resize* free if size is 0 2025-06-15 12:34:15 -04:00
Feoramund a4771ce1b5 mem: Clarify what happens when you free out-of-order in a Small_Stack 2025-06-15 12:34:15 -04:00
Feoramund 21a17c1ae6 mem: Replace auto_cast 2025-06-15 12:34:15 -04:00
Feoramund 8f68c46467 mem: Don't unpoison the header of a Small_Stack allocation 2025-06-15 12:34:15 -04:00
PePerRoNii c08d9c50c8 Changed TCP_Recv_Err to Socket_Info_Err and tested on darwin_arm64 2025-06-15 12:14:59 +07:00
PePerRoNii 42aa8ac383 Implemented _socket_info_error on peer_endpoint and bound_endpoint 2025-06-15 11:17:49 +07:00
PePerRoNii f49bf1abd2 added Socket_Info_Errors Enum 2025-06-15 10:26:06 +07:00
Feoramund 5798151a0e mem: Poison unused memory more thoroughly 2025-06-14 13:21:15 -04:00
Feoramund ae96b276c1 mem: Check if alignment matches on Stack_Allocator resize 2025-06-14 13:21:15 -04:00
Feoramund 837d8cf72c mem: Actually resize when resizing for Stack_Allocator
Changed the check from `bytes` to `err` for safety's sake, too.

This will prevent the potential bug of allocating non-zero memory, then
doing a zeroed resize, which will result in having garbage data in the
initial half.
2025-06-14 13:21:14 -04:00
Feoramund f701aeffd5 mem: Correct wrong error message 2025-06-14 13:21:14 -04:00
Feoramund 7580dc2dd0 mem: Remove pointless check in Scratch_Allocator
The backup allocator is set at `init` which happens even if `Scratch` is
nil at the head of `scratch_alloc_bytes_non_zeroed`.
2025-06-14 13:21:14 -04:00
Feoramund c4f6e973d9 mem: Don't change Scratch_Allocator's backup allocator
The backup allocator is set at `init` and must stay the same for the
lifetime of the Scratch allocator, as this allocator is used to free all
`leaked_allocations`. Changing it could lead to a situation where the
wrong allocator is used to free a leaked allocation.
2025-06-14 13:21:14 -04:00
Feoramund 62b0f71768 mem: Fix comment typo 2025-06-14 13:21:14 -04:00
Feoramund 890245c229 mem: Don't unpoison the header of a Stack allocation 2025-06-14 13:21:14 -04:00
Feoramund 79e5ddaa26 mem: Make stack_resize* free if size is 0
This will cause an error if the memory being resized was not the last
allocation, as should be expected according to the description that this
"acts just like stack_free."
2025-06-14 13:21:14 -04:00
Feoramund 179a8559f6 mem: Add guards against buggy allocators overlapping allocations 2025-06-14 13:21:14 -04:00
Feoramund f627b55cf5 mem: Fix several issues in Scratch_Allocator
1. The size was being adjusted for the alignment which does not make any
   sense without the context of the base pointer. Now we just add the
   `alignment - 1` to the size if needed then adjust the pointer.

2. The root pointer of the last allocation is now stored in order to
   make the free operation more useful (and to cover the right memory
   region for ASan).

3. Resizing now only works on the last allocation instead of any address
   in a valid range, which resulted in overwriting allocations that had
   just been made.

4. `old_memory` is now re-poisoned entirely before the resized range is
   returned with the new range unpoisoned. This will guarantee that
   there are no unpoisoned gaps.

Fixes #2694
2025-06-14 12:35:16 -04:00
Laytan Laats 144daf6fff add macOS Tahoe to odin report and core:sys/info 2025-06-14 00:27:37 +02:00
Jack Mordaunt 17927729dd core/sync/chan: (unbuffered) ack reads
This fixes an issue where a call to close could intercept the dance
between send and recv, causing send to report incorrectly that a value
was not transmitted (when it actually was).
2025-06-13 18:08:44 -03:00
Laytan aa0cffb412 Merge pull request #5328 from laytan/compat-allocator-improvements
mem: compat allocator improvements
2025-06-13 19:41:58 +02:00
Jeroen van Rijn 84eaddbd47 WASI 2025-06-13 18:08:35 +02:00
Jeroen van Rijn 8c8406cc4d stub out get_env for js 2025-06-13 18:00:30 +02:00
Jeroen van Rijn 3862555153 Replace core:posix usage in core:os/os2 2025-06-13 17:49:05 +02:00
Jack Mordaunt 760d8c1cdd core/sync/chan.send: return false if channel is closed while blocked
This commit makes send behave the same as recv: that the call will
return false if the channel is closed while a thread is waiting on the
blocking operation.

Prior logic would have send return true even if the channel was actually
closed rather than read from.

Docs adjusted to make this clear.
Tests added to lock in this behaviour.
2025-06-12 17:35:49 -03:00
Jack Mordaunt c29168f76f core/sync/chan.try_send: avoid blocking if no reader is available
This changes the semantics of try_send to be consistently non-blocking.

That is, if the buffered is full OR there are no readers it returns
false.

The previous behaviour was such that it would block in the latter case
of no reader, and it would wait for a reader. That is problematic
because it produces inconsistent behaviour between buffered and
unbuffered channels which is astonishing and adds complexity to the
caller.

To illustrate the problem with the old behaviour, consider the
try_select operation: if a send-channel happens to be unbuffered the
try_select (which wants to never block) can now block, that unbuffered
send channel is selected (at random) and there is no reader on the other
side. Thus we have unpredictable blocking behaviour, which breaks the
guarantee that try_select never blocks.

If you want a blocking send you can just call "send" (the blocking
variant).

In addition, there is some reader/writer math done inside
can_{send,recv} such that they only report true if there is sufficient
reader/writer capacity. If there is contention we need to ensure that
each reader is paired to exactly one writer.

Consider try_send: if there is a single reader we can send. If there is
a single reader and a single writer, then we cannot send, as that reader
will be paired with the existing writer. Therefore can_send is only true
if there are more readers than writers at the time of check.

NOTE: The original tests don't need to use wait-looping with thread.yield()
or heuristic sleep. Instead we can just use blocking channel operations
rather than non-blocking operations.
2025-06-12 17:35:48 -03:00
Jack Mordaunt c1cd525d9d core/sync/chan.select_raw: call try_select_raw with deprecation warning
Eventually select_raw should be a blocking select operation, but for now
we need to migrate people away.
2025-06-12 16:14:52 -03:00
Jack Mordaunt 96b91849a9 core/sync/chan.try_select_raw: fix doc comment typo
Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
2025-06-12 16:14:52 -03:00
Jack Mordaunt faae81ba61 core/sync/chan.try_select_raw: test hook for testing the toctou
This is necessary because we need to allow the test guarantee against a
rare condition: where a third-party thread steals a value between the
validity checks can_{send,recv} and the channel operation
try_{send,recv}.
2025-06-12 16:14:52 -03:00
Jack Mordaunt 4043be8567 core/sync/chan.try_select_raw: skip nil input messages
This makes the proc easier and safer to call by letting the caller nil
out messages to skip sends.
2025-06-12 16:14:52 -03:00
Jack Mordaunt fb39e5a2f8 core/sync/chan.try_select_raw: clarify loop control flow
Use a label to clarify the continue statements.
2025-06-12 16:14:52 -03:00
Jack Mordaunt d5b7302ac0 core/sync.try_select_raw: fix TOCTOU
Fixes a TOCTOU where the channel could be used between the call to
can_{recv,send} and {recv,send} causing an unexpected blocking
operation.

To do this we use the non-blocking try_{recv,send} and retry the check
in a loop. This guarantees non-blocking select behaviour, at the cost of
spinning if the input channels are highly contended.

Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
2025-06-12 16:14:52 -03:00
Jack Mordaunt be873af003 core/sync.select_raw: rename to try_select_raw
This follows the convention where non-blocking operations are prefixed
with "try" to indicate as much.

Since select_raw in it's current form doesn't block, it should be
try_select_raw, and allow select_raw to name a blocking implementation.
2025-06-12 16:14:52 -03:00
Jack Mordaunt 7f9589922d core/sync.select_raw: return a useful index
This fixes a flaw in the original implementation: the returned index is
actually useless to the caller.

This is because the index returned refers to the internal "candidate"
list. This list is dynamic, and may not have all of the input channels
(if they weren't ready according to chan.can_{recv,send}). That means
the index is not guaranteed to mean anything to the caller.

The fix introduced here is to return the index into the input slice
(recvs,sends) and an enum to specify which input slice that is.

If no selection was made, then (-1, .None) is returned to communicate as
much.

Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
2025-06-12 16:14:51 -03:00
Laytan Laats 67a8b035db mem: compat allocator improvements
1. store alignment instead of original pointer
2. implement .Query_Info
3. poison the header and alignment portion of the allocation
4. .Resize uses `max(orig_alignment, new_alignment)` as it's alignment
   now
5. .Free passes along the original alignment
2025-06-12 20:40:22 +02:00
Laytan Laats 0ed6cdc98e mem/tlsf: fix asan reporting poisoning of already poisoned region
free on tlsf poisons the entire block, while alloc might only unpoison a
part of it (cause it's size is aligned up). This causes free to
potentially poison an already poisoned portion, which is a
use-after-poison.

Because this is "fine" and intended, I opted to just
@no_sanitize_address it.
2025-06-12 19:37:24 +02:00
Jeroen van Rijn 74f70bfbcb Comment 2025-06-12 17:09:33 +02:00