After asking on Stack Overflow about why it wasn't safe to just pass in a raw pointer, I got the following answer:
malloc API handle the size itself, rust alloc api let the user handle the size information, this is often allow to avoid duplicate information but rely on user more. (but normal user of rust don't normally need to know this)
I am wondering where I can get more details on the Rust allocation API? (And why does the Rust allocation API not store the size information itself)?
However, the SO answer is not accurate: generally, C relies on the dynamic data to determine allocation size while Rust relies on generics. Box::from_raw(ptr) will delegate to Box::<u8>::from_raw(), but you need to free a slice and not a single item. So you need Box::<[u8]>::from_raw(), and this is why you did all of the above.
Basically, @vedantroy, you should know that most implementations of Rust allocation APIs do already bundle the associated allocation length within their own bookkeeping, and thus can/may disregard the .size parameter of a dealloc call.
That being said, since there may very well be some platform where some implementation may wish to receive the .size data on dealloc explicitly (IIRC, this may be the case on Windows), then Rust has made the choice to make that part of its API, to be maximally compatible with allocator implementations.
Obviously, this leads to the "freeing end" having to meet this API requirement, as per the very definition of an API contract.
This was deemed acceptable, since when requesting to free something, the owner ought to already be able to know, either statically / at compile-time, or at runtime, how big the thing they own is. Indeed, more generally, one ought to remember at all times how big the thing they are manipulating is