[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFC PATCH] misra: allow conversion from unsigned long to function pointer
On 8/14/25 23:43, Nicola Vetrini wrote: > On 2025-08-14 10:36, Jan Beulich wrote: >> On 13.08.2025 20:27, Dmytro Prokopchuk1 wrote: >>> ... >>> >>> from `vaddr_t' (that is `unsigned long') to `switch_ttbr_fn*' (that >>> is `void(*)(unsigned long)') >>> >>> Signed-off-by: Dmytro Prokopchuk <dmytro_prokopchuk1@xxxxxxxx> >>> --- >>> This is just a RFC patch. >>> The commit message is not important at this stage. >>> >>> I am seeking comments regarding this case. >>> >>> Thanks. >>> --- >>> automation/eclair_analysis/ECLAIR/deviations.ecl | 8 ++++++++ >>> docs/misra/deviations.rst | 10 ++++++++++ >>> docs/misra/rules.rst | 8 +++++++- >>> xen/arch/arm/arm64/mmu/mm.c | 2 ++ >>> 4 files changed, 27 insertions(+), 1 deletion(-) >>> >>> diff --git a/automation/eclair_analysis/ECLAIR/deviations.ecl b/ >>> automation/eclair_analysis/ECLAIR/deviations.ecl >>> index ebce1ceab9..f9fd6076b7 100644 >>> --- a/automation/eclair_analysis/ECLAIR/deviations.ecl >>> +++ b/automation/eclair_analysis/ECLAIR/deviations.ecl >>> @@ -365,6 +365,14 @@ constant expressions are required.\"" >>> } >>> -doc_end >>> >>> +-doc_begin="The conversion from unsigned long to a function pointer >>> does not lose any information, provided that the source type has >>> enough bits to restore it." >>> +-config=MC3A2.R11.1,casts+={safe, >>> + "from(type(canonical(builtin(unsigned long)))) >>> + &&to(type(canonical(__function_pointer_types))) >>> + &&relation(definitely_preserves_value)" >>> +} >>> +-doc_end >>> + > > This check is not quite targeted at this situation, as the behaviour of > different compilers is a bit of a grey area (even GCC, though that works > in practice). The relation is mostly aimed at testing whether the > pointer are represented using the same number of bits as unsigned long > (which happens to be the case fortunately). Hi Nicola. Well, we're telling Eclair the conversion types from() and to(), but can Eclair determine their sizes (in bits) for particular architecture? I mean, is it possible to avoid this "sizeof(unsigned long) == sizeof(void (*)())" in source code using only Eclair configs? Dmytro. > >>> -doc_begin="The conversion from a function pointer to a boolean has >>> a well-known semantics that do not lead to unexpected behaviour." >>> -config=MC3A2.R11.1,casts+={safe, >>> "from(type(canonical(__function_pointer_types))) >>> diff --git a/docs/misra/deviations.rst b/docs/misra/deviations.rst >>> index 3c46a1e47a..27848602f6 100644 >>> --- a/docs/misra/deviations.rst >>> +++ b/docs/misra/deviations.rst >>> @@ -348,6 +348,16 @@ Deviations related to MISRA C:2012 Rules: >>> to store it. >>> - Tagged as `safe` for ECLAIR. >>> >>> + * - R11.1 >>> + - The conversion from unsigned long to a function pointer does >>> not lose any >>> + information or violate type safety assumptions if the >>> unsigned long type >>> + is guaranteed to be at least as large as a function pointer. >>> This ensures >>> + that the function pointer address can be fully represented >>> without >>> + truncation or corruption. Macro BUILD_BUG_ON can be >>> integrated into the >>> + build system to confirm that 'sizeof(unsigned long) >= >>> sizeof(void (*)())' >>> + on all target platforms. >> >> If sizeof(unsigned long) > sizeof(void (*)()), there is loss of >> information. >> Unless (not said here) the unsigned long value itself is the result of >> converting a function pointer to unsigned long. Whether all of that >> together >> can be properly expressed to Eclair I don't know. Hence, as Teddy already >> suggested, == may want specifying instead. >> > > +1; it might be worth to add both the eclair config and the > BUILD_BUG_ON, noting that neither is sufficient on its own: unless the > compiler guarantees not to fiddle with the value is unaltered when cast > back and forth all checks on the number of bits are moot. > >>> --- a/xen/arch/arm/arm64/mmu/mm.c >>> +++ b/xen/arch/arm/arm64/mmu/mm.c >>> @@ -150,6 +150,7 @@ void __init relocate_and_switch_ttbr(uint64_t ttbr) >>> vaddr_t id_addr = virt_to_maddr(relocate_xen); >>> relocate_xen_fn *fn = (relocate_xen_fn *)id_addr; >>> lpae_t pte; >>> + BUILD_BUG_ON(sizeof(unsigned long) < sizeof(fn)); >>> >>> /* Enable the identity mapping in the boot page tables */ >>> update_identity_mapping(true); >>> @@ -178,6 +179,7 @@ void __init switch_ttbr(uint64_t ttbr) >>> vaddr_t id_addr = virt_to_maddr(switch_ttbr_id); >>> switch_ttbr_fn *fn = (switch_ttbr_fn *)id_addr; >>> lpae_t pte; >>> + BUILD_BUG_ON(sizeof(unsigned long) < sizeof(fn)); >>> >>> /* Enable the identity mapping in the boot page tables */ >>> update_identity_mapping(true); >> >> BUILD_BUG_ON() is a statement, not a declaration, and hence wants >> grouping >> as such. Question is whether we indeed want to sprinkle such checks all >> over the code base. (I expect the two cases here aren't all we have.) >> > > +1 as well. I would expect such check to live e.g. in compiler.h or any > similarly general header, since this is a widespread and largely arch- > neutral property that Xen wants to be always true I believe. >
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |