An integer shall not be converted to an invalid pointer

Guideline: An integer shall not be converted to an invalid pointer gui_iv9yCMHRgpE0
status: draft
tags: defect, undefined-behavior
category: <TODO>
decidability: undecidable
scope: system
release: <TODO>

An expression of numeric type shall not be converted to a pointer if the resulting pointer is incorrectly aligned, does not point to an entity of the referenced type, or is an invalid representation.

Rationale: rat_OhxKm751axKw
status: draft
parent needs: gui_iv9yCMHRgpE0

The mapping between pointers and integers must be consistent with the addressing structure of the execution environment. Issues may arise, for example, on architectures that have a segmented memory model.

Non-Compliant Example: non_compl_ex_CkytKjRQezfQ
status: draft
parent needs: gui_iv9yCMHRgpE0

This example makes assumptions about the layout of the address space that do not hold on all platforms. The manipulated address may have discarded part of the original address space, and the flag may silently interfere with the address value. On platforms where pointers are 64-bits this may have particularly unexpected results.

#[allow(dead_code)]
fn f1(flag: u32, ptr: * const u32) {
  /* ... */
  let mut rep = ptr as usize;
  rep = (rep & 0x7fffff) | ((flag as usize) << 23);
  let _p2 = rep as * const u32;
}
Compliant Example: compl_ex_oBoluiKSvREu
status: draft
parent needs: gui_iv9yCMHRgpE0

This compliant solution uses a struct to provide storage for both the pointer and the flag value. This solution is portable to machines of different word sizes, both smaller and larger than 32 bits, working even when pointers cannot be represented in any integer type.

#[allow(dead_code)]
struct PtrFlag {
  pointer: * const u32,
  flag: u32
}

#[allow(dead_code)]
fn f2(flag: u32, ptr: * const u32) {
  let _ptrflag = PtrFlag {
    pointer: ptr,
    flag: flag
  };
  /* ... */
}