in sdk/inc/azure/core/internal/az_precondition_internal.h [85:129]
AZ_NODISCARD AZ_INLINE bool _az_span_is_valid(az_span span, int32_t min_size, bool null_is_valid)
{
if (min_size < 0)
{
return false;
}
uint8_t* const ptr = az_span_ptr(span);
int32_t const span_size = az_span_size(span);
bool result = false;
/* Span is valid if:
The size is greater than or equal to a user defined minimum value AND one of the
following:
- If null_is_valid is true and the pointer in the span is null, the size must also be 0.
- In the case of the pointer not being NULL, the size is greater than or equal to zero.
*/
// On some platforms, in some compilation configurations (Debug), NULL is not 0x0...0. But if you
// initialize a span with { 0 } (or if that span is a part of a structure that is initialized with
// { 0 }) the ptr is not going to be equal to NULL, however the intent of the precondition is to
// disallow default-initialized and null ptrs, so we should treat them the same.
uint8_t* const default_init_ptr = az_span_ptr((az_span){ 0 });
if (null_is_valid)
{
result = (ptr == NULL || ptr == default_init_ptr) ? span_size == 0 : span_size >= 0;
}
else
{
result = (ptr != NULL && ptr != default_init_ptr) && span_size >= 0;
}
// Can't wrap over the end of the address space.
// The biggest theoretical pointer value is "(void*)~0" (0xFFFF...), which is the end of address
// space. We don't attempt to read/write beyond the end of the address space - it is unlikely a
// desired behavior, and it is not defined. So, if the span size is greater than the addresses
// left until the theoretical end of the address space, it is not a valid span.
// Example: (az_span) { .ptr = (uint8_t*)(~0 - 5), .size = 10 } is not a valid span, because most
// likely you end up pointing to 0x0000 at .ptr[6], &.ptr[7] is 0x...0001, etc.
uint8_t* const max_ptr = (uint8_t*)~(uint8_t)0;
result = result && ((size_t)span_size <= (size_t)(max_ptr - ptr));
return result && min_size <= span_size;
}