Re: [PATCH v6 22/26] rust: alloc: implement `Cmalloc` in module allocator_test

From: Benno Lossin
Date: Thu Sep 12 2024 - 04:19:14 EST


On 11.09.24 16:37, Danilo Krummrich wrote:
> On Wed, Sep 11, 2024 at 01:32:31PM +0000, Benno Lossin wrote:
>> On 11.09.24 14:31, Danilo Krummrich wrote:
>>> On Fri, Aug 30, 2024 at 12:25:27AM +0200, Danilo Krummrich wrote:
>>>> On Thu, Aug 29, 2024 at 07:14:18PM +0000, Benno Lossin wrote:
>>>>> On 16.08.24 02:11, Danilo Krummrich wrote:
>>>>>> +
>>>>>> + if layout.size() == 0 {
>>>>>> + // SAFETY: `src` has been created by `Self::alloc_store_data`.
>>>>>
>>>>> This is not true, consider:
>>>>>
>>>>> let ptr = alloc(size = 0);
>>>>> free(ptr)
>>>>>
>>>>> Alloc will return a dangling pointer due to the first if statement and
>>>>> then this function will pass it to `free_read_data`, even though it
>>>>> wasn't created by `alloc_store_data`.
>>>>> This isn't forbidden by the `Allocator` trait function's safety
>>>>> requirements.
>>>>>
>>>>>> + unsafe { Self::free_read_data(src) };
>>>>>> +
>>>>>> + return Ok(NonNull::slice_from_raw_parts(NonNull::dangling(), 0));
>>>>>> + }
>>>>>> +
>>>>>> + let dst = Self::alloc(layout, flags)?;
>>>>>> +
>>>>>> + // SAFETY: `src` has been created by `Self::alloc_store_data`.
>>>>>> + let data = unsafe { Self::data(src) };
>>>>>
>>>>> Same issue here, if the allocation passed in is zero size. I think you
>>>>> have no other choice than to allocate even for zero size requests...
>>>>> Otherwise how would you know that they are zero-sized.
>>>>
>>>> Good catch - gonna fix it.
>>>
>>> Almost got me. :) I think the code is fine, callers are not allowed to pass
>>> pointers to `realloc` and `free`, which haven't been allocated with the same
>>> corresponding allocator or are dangling.
>>
>> But what about the example above (ie the `alloc(size = 0)` and then
>> `free`)?
>
> This never has been valid for the `Allocator` trait. Look at `Kmalloc`,
> `Vmalloc` and `KVmalloc`, they don't allow this either.

That is true.

> We've discussed this already in previous versions of this series, where for this
> purpose, you asked for `old_layout` for `free`. Such that `free` can check if
> the `size` was zero and therefore return without doing anything.

Yes, but that was only about the old_layout parameter (at least that's
what I thought).

>> I guess this all depends on how one interprets the term
>> "existing, valid memory allocation". To me that describes anything an
>> `Allocator` returns via `alloc` and `realloc`, including zero-sized
>> allocations.
>
> I argue that the dangling pointer returned for `size == 0` does not point to any
> allocation in the sense of those allocators. It's just a dangling `[u8]`
> pointer.

Sure, but to me the concept of zero-sized allocations does exist.

>> But if you argue that those are not valid allocations from that
>> allocator, then that is not properly documented in the safety
>> requirements of `Allocator`.
>
> The safety requirements of `Allocator` where proposed by you and I thought they
> consider this aspect?

No, they did not consider this aspect. I was under the impression, that
we would still allow zero-sized allocations (in retrospect, this is
stupid, since dangling pointers shouldn't be passed to `krealloc` etc.).

> `realloc` has:
>
> "If `ptr == Some(p)`, then `p` must point to an existing and valid memory
> allocation created by this allocator."
>
> `free` has:
>
> "`ptr` must point to an existing and valid memory allocation created by this
> `Allocator` and must not be a dangling pointer."
>
> We can add the part about the dangling pointer to `realloc` if you want.

So I think we should do the following:
(1) Add a paragraph to the `Allocator` trait that explains that
zero-sized allocations are not supported.
(2) Add a check to `realloc` for zero-sized allocations + null pointer
(ie a new allocation request) that prints a warning and returns an
error
(3) Instead of writing "existing and valid memory allocation created by
this allocator", I think "valid non-zero-sized memory allocation
created by this allocator" fits better.

---
Cheers,
Benno