[PATCH] misra: consider conversion from UL or (void*) to function pointer as safe

Dmytro Prokopchuk1 posted 1 patch 2 months, 1 week ago
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/9e5e4ff2c7ba0a90a6ac403e2de9318e18949274.1755628705.git.dmytro._5Fprokopchuk1@epam.com
There is a newer version of this series
automation/eclair_analysis/ECLAIR/deviations.ecl |  8 ++++++++
docs/misra/deviations.rst                        | 10 ++++++++++
docs/misra/rules.rst                             |  8 +++++++-
xen/common/version.c                             | 11 +++++++++++
4 files changed, 36 insertions(+), 1 deletion(-)
[PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Dmytro Prokopchuk1 2 months, 1 week ago
Rule 11.1 states as following: "Conversions shall not be performed
between a pointer to a function and any other type."

The conversion from unsigned long or (void *) to a function pointer
is safe in Xen because the architectures it supports (e.g., x86 and
ARM) guarantee compatible representations between these types.

Configure Eclair to avoid reporting violations for conversions from
unsigned long or (void *) to a function pointer.

Add a compile-time assertion to the file 'xen/common/version.c' to
confirm this conversion compatibility across all target platforms
(assuming this file is common for all platforms).

Signed-off-by: Dmytro Prokopchuk <dmytro_prokopchuk1@epam.com>
---
Test CI pipeline:
https://gitlab.com/xen-project/people/dimaprkp4k/xen/-/pipelines/1991940822

RFC thread:
https://patchew.org/Xen/8cbc9e6d881661d0d7a1055cbcef5a65e20522be.1755109168.git.dmytro._5Fprokopchuk1@epam.com/
---
 automation/eclair_analysis/ECLAIR/deviations.ecl |  8 ++++++++
 docs/misra/deviations.rst                        | 10 ++++++++++
 docs/misra/rules.rst                             |  8 +++++++-
 xen/common/version.c                             | 11 +++++++++++
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/automation/eclair_analysis/ECLAIR/deviations.ecl b/automation/eclair_analysis/ECLAIR/deviations.ecl
index 7f3fd35a33..0083c9c505 100644
--- a/automation/eclair_analysis/ECLAIR/deviations.ecl
+++ b/automation/eclair_analysis/ECLAIR/deviations.ecl
@@ -375,6 +375,14 @@ constant expressions are required.\""
 }
 -doc_end
 
+-doc_begin="The conversion from unsigned long or (void *) to a function pointer is safe because the architectures Xen supports (e.g., x86 and ARM) guarantee compatible representations between these types."
+-config=MC3A2.R11.1,casts+={safe,
+  "from(type(canonical(builtin(unsigned long)||pointer(builtin(void)))))
+   &&to(type(canonical(__function_pointer_types)))
+   &&relation(definitely_preserves_value)"
+}
+-doc_end
+
 -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 2119066531..74540e0565 100644
--- a/docs/misra/deviations.rst
+++ b/docs/misra/deviations.rst
@@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
        to store it.
      - Tagged as `safe` for ECLAIR.
 
+   * - R11.1
+     - The conversion from unsigned long or (void \*) to a function pointer does
+       not lose any information or violate type safety assumptions if unsigned
+       long or (void \*) type is guaranteed to be the same bit size as a
+       function pointer. This ensures that the function pointer can be fully
+       represented without truncation or corruption. The macro BUILD_BUG_ON is
+       integrated into xen/common/version.c to confirm conversion compatibility
+       across all target platforms.
+     - Tagged as `safe` for ECLAIR.
+
    * - R11.1
      - The conversion from a function pointer to a boolean has a well-known
        semantics that do not lead to unexpected behaviour.
diff --git a/docs/misra/rules.rst b/docs/misra/rules.rst
index a2e4e9f4ff..ff48a90963 100644
--- a/docs/misra/rules.rst
+++ b/docs/misra/rules.rst
@@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
      - All conversions to integer types are permitted if the destination
        type has enough bits to hold the entire value. Conversions to bool
        and void* are permitted. Conversions from 'void noreturn (*)(...)'
-       to 'void (*)(...)' are permitted.
+       to 'void (*)(...)' are permitted. Conversions from unsigned long or
+       (void \*) to a function pointer are permitted if the source type has
+       enough bits to restore function pointer without truncation or corruption.
+       Example::
+
+           unsigned long func_addr = (unsigned long)&some_function;
+           void (*restored_func)(void) = (void (*)(void))func_addr;
 
    * - `Rule 11.2 <https://gitlab.com/MISRA/MISRA-C/MISRA-C-2012/Example-Suite/-/blob/master/R_11_02.c>`_
      - Required
diff --git a/xen/common/version.c b/xen/common/version.c
index 553b97ba9b..7091a6d440 100644
--- a/xen/common/version.c
+++ b/xen/common/version.c
@@ -217,6 +217,17 @@ void __init xen_build_init(void)
 #endif /* CONFIG_X86 */
 }
 #endif /* BUILD_ID */
+
+static void __init __maybe_unused build_assertions(void)
+{
+    /*
+     * To confirm conversion compatibility between unsigned long, (void *)
+     * and function pointers for all supported architectures.
+     */
+    BUILD_BUG_ON(sizeof(unsigned long) != sizeof(void (*)(void)));
+    BUILD_BUG_ON(sizeof(void *) != sizeof(void (*)(void)));
+}
+
 /*
  * Local variables:
  * mode: C
-- 
2.43.0
Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Jan Beulich 2 months, 1 week ago
On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
> Rule 11.1 states as following: "Conversions shall not be performed
> between a pointer to a function and any other type."
> 
> The conversion from unsigned long or (void *) to a function pointer
> is safe in Xen because the architectures it supports (e.g., x86 and
> ARM) guarantee compatible representations between these types.

I think we need to be as precise as possible here. The architectures
guarantee nothing, they only offer necessary fundamentals. In the
Windows x86 ABI, for example, you can't convert pointers to/from longs
without losing data. What we build upon is what respective ABIs say,
possibly in combination of implementation specifics left to compilers.

> --- a/docs/misra/deviations.rst
> +++ b/docs/misra/deviations.rst
> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>         to store it.
>       - Tagged as `safe` for ECLAIR.
>  
> +   * - R11.1
> +     - The conversion from unsigned long or (void \*) to a function pointer does
> +       not lose any information or violate type safety assumptions if unsigned
> +       long or (void \*) type is guaranteed to be the same bit size as a
> +       function pointer. This ensures that the function pointer can be fully
> +       represented without truncation or corruption. The macro BUILD_BUG_ON is
> +       integrated into xen/common/version.c to confirm conversion compatibility
> +       across all target platforms.
> +     - Tagged as `safe` for ECLAIR.

Why the escaping of * here, when ...

> --- a/docs/misra/rules.rst
> +++ b/docs/misra/rules.rst
> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>       - All conversions to integer types are permitted if the destination
>         type has enough bits to hold the entire value. Conversions to bool
>         and void* are permitted. Conversions from 'void noreturn (*)(...)'
> -       to 'void (*)(...)' are permitted.
> +       to 'void (*)(...)' are permitted. Conversions from unsigned long or
> +       (void \*) to a function pointer are permitted if the source type has
> +       enough bits to restore function pointer without truncation or corruption.
> +       Example::
> +
> +           unsigned long func_addr = (unsigned long)&some_function;
> +           void (*restored_func)(void) = (void (*)(void))func_addr;

... context here suggests they work fine un-escaped, and you even add some un-
escaped instances as well. Perhaps I'm simply unaware of some peculiarity?

Jan
Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Nicola Vetrini 2 months, 1 week ago
On 2025-08-21 10:01, Jan Beulich wrote:
> On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
>> Rule 11.1 states as following: "Conversions shall not be performed
>> between a pointer to a function and any other type."
>> 
>> The conversion from unsigned long or (void *) to a function pointer
>> is safe in Xen because the architectures it supports (e.g., x86 and
>> ARM) guarantee compatible representations between these types.
> 
> I think we need to be as precise as possible here. The architectures
> guarantee nothing, they only offer necessary fundamentals. In the
> Windows x86 ABI, for example, you can't convert pointers to/from longs
> without losing data. What we build upon is what respective ABIs say,
> possibly in combination of implementation specifics left to compilers.
> 

+1, a mention of the compilers and targets this deviation relies upon is 
needed.

>> --- a/docs/misra/deviations.rst
>> +++ b/docs/misra/deviations.rst
>> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>>         to store it.
>>       - Tagged as `safe` for ECLAIR.
>> 
>> +   * - R11.1
>> +     - The conversion from unsigned long or (void \*) to a function 
>> pointer does
>> +       not lose any information or violate type safety assumptions if 
>> unsigned
>> +       long or (void \*) type is guaranteed to be the same bit size 
>> as a
>> +       function pointer. This ensures that the function pointer can 
>> be fully
>> +       represented without truncation or corruption. The macro 
>> BUILD_BUG_ON is
>> +       integrated into xen/common/version.c to confirm conversion 
>> compatibility
>> +       across all target platforms.
>> +     - Tagged as `safe` for ECLAIR.
> 
> Why the escaping of * here, when ...
> 
>> --- a/docs/misra/rules.rst
>> +++ b/docs/misra/rules.rst
>> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>>       - All conversions to integer types are permitted if the 
>> destination
>>         type has enough bits to hold the entire value. Conversions to 
>> bool
>>         and void* are permitted. Conversions from 'void noreturn 
>> (*)(...)'
>> -       to 'void (*)(...)' are permitted.
>> +       to 'void (*)(...)' are permitted. Conversions from unsigned 
>> long or
>> +       (void \*) to a function pointer are permitted if the source 
>> type has
>> +       enough bits to restore function pointer without truncation or 
>> corruption.
>> +       Example::
>> +
>> +           unsigned long func_addr = (unsigned long)&some_function;
>> +           void (*restored_func)(void) = (void (*)(void))func_addr;
> 
> ... context here suggests they work fine un-escaped, and you even add 
> some un-
> escaped instances as well. Perhaps I'm simply unaware of some 
> peculiarity?
> 

This is a literal rst block, while the other is not (* acts as a bullet 
point in rst iirc)

> Jan

-- 
Nicola Vetrini, B.Sc.
Software Engineer
BUGSENG (https://bugseng.com)
LinkedIn: https://www.linkedin.com/in/nicola-vetrini-a42471253
Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Dmytro Prokopchuk1 2 months, 1 week ago

On 8/21/25 11:25, Nicola Vetrini wrote:
> On 2025-08-21 10:01, Jan Beulich wrote:
>> On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
>>> Rule 11.1 states as following: "Conversions shall not be performed
>>> between a pointer to a function and any other type."
>>>
>>> The conversion from unsigned long or (void *) to a function pointer
>>> is safe in Xen because the architectures it supports (e.g., x86 and
>>> ARM) guarantee compatible representations between these types.
>>
>> I think we need to be as precise as possible here. The architectures
>> guarantee nothing, they only offer necessary fundamentals. In the
>> Windows x86 ABI, for example, you can't convert pointers to/from longs
>> without losing data. What we build upon is what respective ABIs say,
>> possibly in combination of implementation specifics left to compilers.
>>
> 
> +1, a mention of the compilers and targets this deviation relies upon is 
> needed.

Maybe with this wording:

This deviation is based on the guarantees provided by the specific ABIs
(e.g., ARM AAPCS) and compilers (e.g., GCC) supported in Xen. These ABIs
guarantee compatible representations for 'void *', 'unsigned long' and
function pointers for the supported target platforms. This behavior is
architecture-specific and may not be portable outside of supported
environments.

> 
>>> --- a/docs/misra/deviations.rst
>>> +++ b/docs/misra/deviations.rst
>>> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>>>         to store it.
>>>       - Tagged as `safe` for ECLAIR.
>>>
>>> +   * - R11.1
>>> +     - The conversion from unsigned long or (void \*) to a function 
>>> pointer does
>>> +       not lose any information or violate type safety assumptions 
>>> if unsigned
>>> +       long or (void \*) type is guaranteed to be the same bit size 
>>> as a
>>> +       function pointer. This ensures that the function pointer can 
>>> be fully
>>> +       represented without truncation or corruption. The macro 
>>> BUILD_BUG_ON is
>>> +       integrated into xen/common/version.c to confirm conversion 
>>> compatibility
>>> +       across all target platforms.
>>> +     - Tagged as `safe` for ECLAIR.
>>
>> Why the escaping of * here, when ...
>>
>>> --- a/docs/misra/rules.rst
>>> +++ b/docs/misra/rules.rst
>>> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>>>       - All conversions to integer types are permitted if the 
>>> destination
>>>         type has enough bits to hold the entire value. Conversions to 
>>> bool
>>>         and void* are permitted. Conversions from 'void noreturn (*) 
>>> (...)'
>>> -       to 'void (*)(...)' are permitted.
>>> +       to 'void (*)(...)' are permitted. Conversions from unsigned 
>>> long or
>>> +       (void \*) to a function pointer are permitted if the source 
>>> type has
>>> +       enough bits to restore function pointer without truncation or 
>>> corruption.
>>> +       Example::
>>> +
>>> +           unsigned long func_addr = (unsigned long)&some_function;
>>> +           void (*restored_func)(void) = (void (*)(void))func_addr;
>>
>> ... context here suggests they work fine un-escaped, and you even add 
>> some un-
>> escaped instances as well. Perhaps I'm simply unaware of some 
>> peculiarity?
>>
> 
> This is a literal rst block, while the other is not (* acts as a bullet 
> point in rst iirc)

This is how "sphinx-build" tool interprets this.
1. * inside single quotes '' -> looks normal, e.g. ‘void (*)(…)’
2. * without quotes -> warning
deviations.rst:369: WARNING: Inline emphasis start-string without 
end-string. [docutils]
3. \* -> looks normal, e.g. (void *)

Because that we need such format: \*

Dmytro.

> 
>> Jan
> 
Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Nicola Vetrini 2 months ago
On 2025-08-22 18:34, Dmytro Prokopchuk1 wrote:
> On 8/21/25 11:25, Nicola Vetrini wrote:
>> On 2025-08-21 10:01, Jan Beulich wrote:
>>> On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
>>>> Rule 11.1 states as following: "Conversions shall not be performed
>>>> between a pointer to a function and any other type."
>>>> 
>>>> The conversion from unsigned long or (void *) to a function pointer
>>>> is safe in Xen because the architectures it supports (e.g., x86 and
>>>> ARM) guarantee compatible representations between these types.
>>> 
>>> I think we need to be as precise as possible here. The architectures
>>> guarantee nothing, they only offer necessary fundamentals. In the
>>> Windows x86 ABI, for example, you can't convert pointers to/from 
>>> longs
>>> without losing data. What we build upon is what respective ABIs say,
>>> possibly in combination of implementation specifics left to 
>>> compilers.
>>> 
>> 
>> +1, a mention of the compilers and targets this deviation relies upon 
>> is
>> needed.
> 
> Maybe with this wording:
> 
> This deviation is based on the guarantees provided by the specific ABIs
> (e.g., ARM AAPCS) and compilers (e.g., GCC) supported in Xen. These 
> ABIs

s/supported in/supported by/

> guarantee compatible representations for 'void *', 'unsigned long' and
> function pointers for the supported target platforms. This behavior is

It's not just about the guarantees of the ABIs: it's the behavior of the 
compiler for those ABIs that makes this safe or unsafe. If present, such 
documentation should be included

> architecture-specific and may not be portable outside of supported
> environments.
> 
>> 
>>>> --- a/docs/misra/deviations.rst
>>>> +++ b/docs/misra/deviations.rst
>>>> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>>>>         to store it.
>>>>       - Tagged as `safe` for ECLAIR.
>>>> 
>>>> +   * - R11.1
>>>> +     - The conversion from unsigned long or (void \*) to a function
>>>> pointer does
>>>> +       not lose any information or violate type safety assumptions
>>>> if unsigned
>>>> +       long or (void \*) type is guaranteed to be the same bit size
>>>> as a
>>>> +       function pointer. This ensures that the function pointer can
>>>> be fully
>>>> +       represented without truncation or corruption. The macro
>>>> BUILD_BUG_ON is
>>>> +       integrated into xen/common/version.c to confirm conversion
>>>> compatibility
>>>> +       across all target platforms.
>>>> +     - Tagged as `safe` for ECLAIR.
>>> 
>>> Why the escaping of * here, when ...
>>> 
>>>> --- a/docs/misra/rules.rst
>>>> +++ b/docs/misra/rules.rst
>>>> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>>>>       - All conversions to integer types are permitted if the
>>>> destination
>>>>         type has enough bits to hold the entire value. Conversions 
>>>> to
>>>> bool
>>>>         and void* are permitted. Conversions from 'void noreturn (*)
>>>> (...)'
>>>> -       to 'void (*)(...)' are permitted.
>>>> +       to 'void (*)(...)' are permitted. Conversions from unsigned
>>>> long or
>>>> +       (void \*) to a function pointer are permitted if the source
>>>> type has
>>>> +       enough bits to restore function pointer without truncation 
>>>> or
>>>> corruption.
>>>> +       Example::
>>>> +
>>>> +           unsigned long func_addr = (unsigned long)&some_function;
>>>> +           void (*restored_func)(void) = (void (*)(void))func_addr;
>>> 
>>> ... context here suggests they work fine un-escaped, and you even add
>>> some un-
>>> escaped instances as well. Perhaps I'm simply unaware of some
>>> peculiarity?
>>> 
>> 
>> This is a literal rst block, while the other is not (* acts as a 
>> bullet
>> point in rst iirc)
> 
> This is how "sphinx-build" tool interprets this.
> 1. * inside single quotes '' -> looks normal, e.g. ‘void (*)(…)’
> 2. * without quotes -> warning
> deviations.rst:369: WARNING: Inline emphasis start-string without
> end-string. [docutils]
> 3. \* -> looks normal, e.g. (void *)
> 
> Because that we need such format: \*
> 
> Dmytro.
> 
>> 
>>> Jan
>> 

-- 
Nicola Vetrini, B.Sc.
Software Engineer
BUGSENG (https://bugseng.com)
LinkedIn: https://www.linkedin.com/in/nicola-vetrini-a42471253

Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Nicola Vetrini 2 months ago
On 2025-08-25 14:53, Nicola Vetrini wrote:
> On 2025-08-22 18:34, Dmytro Prokopchuk1 wrote:
>> On 8/21/25 11:25, Nicola Vetrini wrote:
>>> On 2025-08-21 10:01, Jan Beulich wrote:
>>>> On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
>>>>> Rule 11.1 states as following: "Conversions shall not be performed
>>>>> between a pointer to a function and any other type."
>>>>> 
>>>>> The conversion from unsigned long or (void *) to a function pointer
>>>>> is safe in Xen because the architectures it supports (e.g., x86 and
>>>>> ARM) guarantee compatible representations between these types.
>>>> 
>>>> I think we need to be as precise as possible here. The architectures
>>>> guarantee nothing, they only offer necessary fundamentals. In the
>>>> Windows x86 ABI, for example, you can't convert pointers to/from 
>>>> longs
>>>> without losing data. What we build upon is what respective ABIs say,
>>>> possibly in combination of implementation specifics left to 
>>>> compilers.
>>>> 
>>> 
>>> +1, a mention of the compilers and targets this deviation relies upon 
>>> is
>>> needed.
>> 
>> Maybe with this wording:
>> 
>> This deviation is based on the guarantees provided by the specific 
>> ABIs
>> (e.g., ARM AAPCS) and compilers (e.g., GCC) supported in Xen. These 
>> ABIs
> 
> s/supported in/supported by/
> 
>> guarantee compatible representations for 'void *', 'unsigned long' and
>> function pointers for the supported target platforms. This behavior is
> 
> It's not just about the guarantees of the ABIs: it's the behavior of 
> the compiler for those ABIs that makes this safe or unsafe. If present, 
> such documentation should be included
> 

In any case, provided that the wording can be adjusted:

Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>

>> architecture-specific and may not be portable outside of supported
>> environments.
>> 
>>> 
>>>>> --- a/docs/misra/deviations.rst
>>>>> +++ b/docs/misra/deviations.rst
>>>>> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>>>>>         to store it.
>>>>>       - Tagged as `safe` for ECLAIR.
>>>>> 
>>>>> +   * - R11.1
>>>>> +     - The conversion from unsigned long or (void \*) to a 
>>>>> function
>>>>> pointer does
>>>>> +       not lose any information or violate type safety assumptions
>>>>> if unsigned
>>>>> +       long or (void \*) type is guaranteed to be the same bit 
>>>>> size
>>>>> as a
>>>>> +       function pointer. This ensures that the function pointer 
>>>>> can
>>>>> be fully
>>>>> +       represented without truncation or corruption. The macro
>>>>> BUILD_BUG_ON is
>>>>> +       integrated into xen/common/version.c to confirm conversion
>>>>> compatibility
>>>>> +       across all target platforms.
>>>>> +     - Tagged as `safe` for ECLAIR.
>>>> 
>>>> Why the escaping of * here, when ...
>>>> 
>>>>> --- a/docs/misra/rules.rst
>>>>> +++ b/docs/misra/rules.rst
>>>>> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>>>>>       - All conversions to integer types are permitted if the
>>>>> destination
>>>>>         type has enough bits to hold the entire value. Conversions 
>>>>> to
>>>>> bool
>>>>>         and void* are permitted. Conversions from 'void noreturn 
>>>>> (*)
>>>>> (...)'
>>>>> -       to 'void (*)(...)' are permitted.
>>>>> +       to 'void (*)(...)' are permitted. Conversions from unsigned
>>>>> long or
>>>>> +       (void \*) to a function pointer are permitted if the source
>>>>> type has
>>>>> +       enough bits to restore function pointer without truncation 
>>>>> or
>>>>> corruption.
>>>>> +       Example::
>>>>> +
>>>>> +           unsigned long func_addr = (unsigned 
>>>>> long)&some_function;
>>>>> +           void (*restored_func)(void) = (void 
>>>>> (*)(void))func_addr;
>>>> 
>>>> ... context here suggests they work fine un-escaped, and you even 
>>>> add
>>>> some un-
>>>> escaped instances as well. Perhaps I'm simply unaware of some
>>>> peculiarity?
>>>> 
>>> 
>>> This is a literal rst block, while the other is not (* acts as a 
>>> bullet
>>> point in rst iirc)
>> 
>> This is how "sphinx-build" tool interprets this.
>> 1. * inside single quotes '' -> looks normal, e.g. ‘void (*)(…)’
>> 2. * without quotes -> warning
>> deviations.rst:369: WARNING: Inline emphasis start-string without
>> end-string. [docutils]
>> 3. \* -> looks normal, e.g. (void *)
>> 
>> Because that we need such format: \*
>> 
>> Dmytro.
>> 
>>> 
>>>> Jan
>>> 

-- 
Nicola Vetrini, B.Sc.
Software Engineer
BUGSENG (https://bugseng.com)
LinkedIn: https://www.linkedin.com/in/nicola-vetrini-a42471253

Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Dmytro Prokopchuk1 2 months ago

On 8/25/25 16:08, Nicola Vetrini wrote:
> On 2025-08-25 14:53, Nicola Vetrini wrote:
>> On 2025-08-22 18:34, Dmytro Prokopchuk1 wrote:
>>> On 8/21/25 11:25, Nicola Vetrini wrote:
>>>> On 2025-08-21 10:01, Jan Beulich wrote:
>>>>> On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
>>>>>> Rule 11.1 states as following: "Conversions shall not be performed
>>>>>> between a pointer to a function and any other type."
>>>>>>
>>>>>> The conversion from unsigned long or (void *) to a function pointer
>>>>>> is safe in Xen because the architectures it supports (e.g., x86 and
>>>>>> ARM) guarantee compatible representations between these types.
>>>>>
>>>>> I think we need to be as precise as possible here. The architectures
>>>>> guarantee nothing, they only offer necessary fundamentals. In the
>>>>> Windows x86 ABI, for example, you can't convert pointers to/from longs
>>>>> without losing data. What we build upon is what respective ABIs say,
>>>>> possibly in combination of implementation specifics left to compilers.
>>>>>
>>>>
>>>> +1, a mention of the compilers and targets this deviation relies 
>>>> upon is
>>>> needed.
>>>
>>> Maybe with this wording:
>>>
>>> This deviation is based on the guarantees provided by the specific ABIs
>>> (e.g., ARM AAPCS) and compilers (e.g., GCC) supported in Xen. These ABIs
>>
>> s/supported in/supported by/
>>
>>> guarantee compatible representations for 'void *', 'unsigned long' and
>>> function pointers for the supported target platforms. This behavior is
>>
>> It's not just about the guarantees of the ABIs: it's the behavior of 
>> the compiler for those ABIs that makes this safe or unsafe. If 
>> present, such documentation should be included
>>
> 
> In any case, provided that the wording can be adjusted:
> 
> Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>

Updated wording:

This deviation from Rule 11.1 relies on both ABI definitions and compiler
implementations supported by Xen. The System V x86_64 ABI and the AArch64
ELF ABI define consistent and compatible representations (i.e., having
the same size and memory layout) for 'void *', 'unsigned long', and function
pointers, enabling safe conversions between these types without data loss
or corruption. Additionally, GCC and Clang, faithfully implement the ABI
specifications, ensuring that the generated machine code conforms to these
guarantees. Developers must note that this behavior is not universal and
depends on platform-specific ABIs and compiler implementations.

References:
- System V x86_64 ABI: 
https://gitlab.com/x86-psABIs/x86-64-ABI/-/jobs/artifacts/master/raw/x86-64-ABI/abi.pdf?job=build
- AArch64 ELF ABI: https://github.com/ARM-software/abi-aa/releases
- GCC: https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
- Clang: https://clang.llvm.org/docs/CrossCompilation.html

Thanks,
Dmytro.
> 
>>> architecture-specific and may not be portable outside of supported
>>> environments.
>>>
>>>>
>>>>>> --- a/docs/misra/deviations.rst
>>>>>> +++ b/docs/misra/deviations.rst
>>>>>> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>>>>>>         to store it.
>>>>>>       - Tagged as `safe` for ECLAIR.
>>>>>>
>>>>>> +   * - R11.1
>>>>>> +     - The conversion from unsigned long or (void \*) to a function
>>>>>> pointer does
>>>>>> +       not lose any information or violate type safety assumptions
>>>>>> if unsigned
>>>>>> +       long or (void \*) type is guaranteed to be the same bit size
>>>>>> as a
>>>>>> +       function pointer. This ensures that the function pointer can
>>>>>> be fully
>>>>>> +       represented without truncation or corruption. The macro
>>>>>> BUILD_BUG_ON is
>>>>>> +       integrated into xen/common/version.c to confirm conversion
>>>>>> compatibility
>>>>>> +       across all target platforms.
>>>>>> +     - Tagged as `safe` for ECLAIR.
>>>>>
>>>>> Why the escaping of * here, when ...
>>>>>
>>>>>> --- a/docs/misra/rules.rst
>>>>>> +++ b/docs/misra/rules.rst
>>>>>> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>>>>>>       - All conversions to integer types are permitted if the
>>>>>> destination
>>>>>>         type has enough bits to hold the entire value. Conversions to
>>>>>> bool
>>>>>>         and void* are permitted. Conversions from 'void noreturn (*)
>>>>>> (...)'
>>>>>> -       to 'void (*)(...)' are permitted.
>>>>>> +       to 'void (*)(...)' are permitted. Conversions from unsigned
>>>>>> long or
>>>>>> +       (void \*) to a function pointer are permitted if the source
>>>>>> type has
>>>>>> +       enough bits to restore function pointer without truncation or
>>>>>> corruption.
>>>>>> +       Example::
>>>>>> +
>>>>>> +           unsigned long func_addr = (unsigned long)&some_function;
>>>>>> +           void (*restored_func)(void) = (void (*)(void))func_addr;
>>>>>
>>>>> ... context here suggests they work fine un-escaped, and you even add
>>>>> some un-
>>>>> escaped instances as well. Perhaps I'm simply unaware of some
>>>>> peculiarity?
>>>>>
>>>>
>>>> This is a literal rst block, while the other is not (* acts as a bullet
>>>> point in rst iirc)
>>>
>>> This is how "sphinx-build" tool interprets this.
>>> 1. * inside single quotes '' -> looks normal, e.g. ‘void (*)(…)’
>>> 2. * without quotes -> warning
>>> deviations.rst:369: WARNING: Inline emphasis start-string without
>>> end-string. [docutils]
>>> 3. \* -> looks normal, e.g. (void *)
>>>
>>> Because that we need such format: \*
>>>
>>> Dmytro.
>>>
>>>>
>>>>> Jan
>>>>
> 
Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Nicola Vetrini 2 months ago
On 2025-08-28 17:54, Dmytro Prokopchuk1 wrote:
> On 8/25/25 16:08, Nicola Vetrini wrote:
>> On 2025-08-25 14:53, Nicola Vetrini wrote:
>>> On 2025-08-22 18:34, Dmytro Prokopchuk1 wrote:
>>>> On 8/21/25 11:25, Nicola Vetrini wrote:
>>>>> On 2025-08-21 10:01, Jan Beulich wrote:
>>>>>> On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
>>>>>>> Rule 11.1 states as following: "Conversions shall not be 
>>>>>>> performed
>>>>>>> between a pointer to a function and any other type."
>>>>>>> 
>>>>>>> The conversion from unsigned long or (void *) to a function 
>>>>>>> pointer
>>>>>>> is safe in Xen because the architectures it supports (e.g., x86 
>>>>>>> and
>>>>>>> ARM) guarantee compatible representations between these types.
>>>>>> 
>>>>>> I think we need to be as precise as possible here. The 
>>>>>> architectures
>>>>>> guarantee nothing, they only offer necessary fundamentals. In the
>>>>>> Windows x86 ABI, for example, you can't convert pointers to/from 
>>>>>> longs
>>>>>> without losing data. What we build upon is what respective ABIs 
>>>>>> say,
>>>>>> possibly in combination of implementation specifics left to 
>>>>>> compilers.
>>>>>> 
>>>>> 
>>>>> +1, a mention of the compilers and targets this deviation relies
>>>>> upon is
>>>>> needed.
>>>> 
>>>> Maybe with this wording:
>>>> 
>>>> This deviation is based on the guarantees provided by the specific 
>>>> ABIs
>>>> (e.g., ARM AAPCS) and compilers (e.g., GCC) supported in Xen. These 
>>>> ABIs
>>> 
>>> s/supported in/supported by/
>>> 
>>>> guarantee compatible representations for 'void *', 'unsigned long' 
>>>> and
>>>> function pointers for the supported target platforms. This behavior 
>>>> is
>>> 
>>> It's not just about the guarantees of the ABIs: it's the behavior of
>>> the compiler for those ABIs that makes this safe or unsafe. If
>>> present, such documentation should be included
>>> 
>> 
>> In any case, provided that the wording can be adjusted:
>> 
>> Reviewed-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
> 
> Updated wording:
> 
> This deviation from Rule 11.1 relies on both ABI definitions and 
> compiler
> implementations supported by Xen. The System V x86_64 ABI and the 
> AArch64
> ELF ABI define consistent and compatible representations (i.e., having
> the same size and memory layout) for 'void *', 'unsigned long', and 
> function
> pointers, enabling safe conversions between these types without data 
> loss
> or corruption. Additionally, GCC and Clang, faithfully implement the 
> ABI
> specifications, ensuring that the generated machine code conforms to 
> these
> guarantees. Developers must note that this behavior is not universal 
> and
> depends on platform-specific ABIs and compiler implementations.
> 

LGTM.

> References:
> - System V x86_64 ABI:
> https://gitlab.com/x86-psABIs/x86-64-ABI/-/jobs/artifacts/master/raw/x86-64-ABI/abi.pdf?job=build
> - AArch64 ELF ABI: https://github.com/ARM-software/abi-aa/releases
> - GCC: https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
> - Clang: https://clang.llvm.org/docs/CrossCompilation.html
> 
> Thanks,
> Dmytro.
>> 
>>>> architecture-specific and may not be portable outside of supported
>>>> environments.
>>>> 
>>>>> 
>>>>>>> --- a/docs/misra/deviations.rst
>>>>>>> +++ b/docs/misra/deviations.rst
>>>>>>> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>>>>>>>         to store it.
>>>>>>>       - Tagged as `safe` for ECLAIR.
>>>>>>> 
>>>>>>> +   * - R11.1
>>>>>>> +     - The conversion from unsigned long or (void \*) to a 
>>>>>>> function
>>>>>>> pointer does
>>>>>>> +       not lose any information or violate type safety 
>>>>>>> assumptions
>>>>>>> if unsigned
>>>>>>> +       long or (void \*) type is guaranteed to be the same bit 
>>>>>>> size
>>>>>>> as a
>>>>>>> +       function pointer. This ensures that the function pointer 
>>>>>>> can
>>>>>>> be fully
>>>>>>> +       represented without truncation or corruption. The macro
>>>>>>> BUILD_BUG_ON is
>>>>>>> +       integrated into xen/common/version.c to confirm 
>>>>>>> conversion
>>>>>>> compatibility
>>>>>>> +       across all target platforms.
>>>>>>> +     - Tagged as `safe` for ECLAIR.
>>>>>> 
>>>>>> Why the escaping of * here, when ...
>>>>>> 
>>>>>>> --- a/docs/misra/rules.rst
>>>>>>> +++ b/docs/misra/rules.rst
>>>>>>> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>>>>>>>       - All conversions to integer types are permitted if the
>>>>>>> destination
>>>>>>>         type has enough bits to hold the entire value. 
>>>>>>> Conversions to
>>>>>>> bool
>>>>>>>         and void* are permitted. Conversions from 'void noreturn 
>>>>>>> (*)
>>>>>>> (...)'
>>>>>>> -       to 'void (*)(...)' are permitted.
>>>>>>> +       to 'void (*)(...)' are permitted. Conversions from 
>>>>>>> unsigned
>>>>>>> long or
>>>>>>> +       (void \*) to a function pointer are permitted if the 
>>>>>>> source
>>>>>>> type has
>>>>>>> +       enough bits to restore function pointer without 
>>>>>>> truncation or
>>>>>>> corruption.
>>>>>>> +       Example::
>>>>>>> +
>>>>>>> +           unsigned long func_addr = (unsigned 
>>>>>>> long)&some_function;
>>>>>>> +           void (*restored_func)(void) = (void 
>>>>>>> (*)(void))func_addr;
>>>>>> 
>>>>>> ... context here suggests they work fine un-escaped, and you even 
>>>>>> add
>>>>>> some un-
>>>>>> escaped instances as well. Perhaps I'm simply unaware of some
>>>>>> peculiarity?
>>>>>> 
>>>>> 
>>>>> This is a literal rst block, while the other is not (* acts as a 
>>>>> bullet
>>>>> point in rst iirc)
>>>> 
>>>> This is how "sphinx-build" tool interprets this.
>>>> 1. * inside single quotes '' -> looks normal, e.g. ‘void (*)(…)’
>>>> 2. * without quotes -> warning
>>>> deviations.rst:369: WARNING: Inline emphasis start-string without
>>>> end-string. [docutils]
>>>> 3. \* -> looks normal, e.g. (void *)
>>>> 
>>>> Because that we need such format: \*
>>>> 
>>>> Dmytro.
>>>> 
>>>>> 
>>>>>> Jan
>>>>> 
>> 

-- 
Nicola Vetrini, B.Sc.
Software Engineer
BUGSENG (https://bugseng.com)
LinkedIn: https://www.linkedin.com/in/nicola-vetrini-a42471253

Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Jan Beulich 2 months ago
On 22.08.2025 18:34, Dmytro Prokopchuk1 wrote:
> On 8/21/25 11:25, Nicola Vetrini wrote:
>> On 2025-08-21 10:01, Jan Beulich wrote:
>>> On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
>>>> Rule 11.1 states as following: "Conversions shall not be performed
>>>> between a pointer to a function and any other type."
>>>>
>>>> The conversion from unsigned long or (void *) to a function pointer
>>>> is safe in Xen because the architectures it supports (e.g., x86 and
>>>> ARM) guarantee compatible representations between these types.
>>>
>>> I think we need to be as precise as possible here. The architectures
>>> guarantee nothing, they only offer necessary fundamentals. In the
>>> Windows x86 ABI, for example, you can't convert pointers to/from longs
>>> without losing data. What we build upon is what respective ABIs say,
>>> possibly in combination of implementation specifics left to compilers.
>>>
>>
>> +1, a mention of the compilers and targets this deviation relies upon is 
>> needed.
> 
> Maybe with this wording:
> 
> This deviation is based on the guarantees provided by the specific ABIs
> (e.g., ARM AAPCS) and compilers (e.g., GCC) supported in Xen. These ABIs
> guarantee compatible representations for 'void *', 'unsigned long' and
> function pointers for the supported target platforms. This behavior is
> architecture-specific and may not be portable outside of supported
> environments.

Reads okay to me; for Arm64 I can only assume the psABI indeed makes this
guarantee.

>>>> --- a/docs/misra/deviations.rst
>>>> +++ b/docs/misra/deviations.rst
>>>> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>>>>         to store it.
>>>>       - Tagged as `safe` for ECLAIR.
>>>>
>>>> +   * - R11.1
>>>> +     - The conversion from unsigned long or (void \*) to a function 
>>>> pointer does
>>>> +       not lose any information or violate type safety assumptions 
>>>> if unsigned
>>>> +       long or (void \*) type is guaranteed to be the same bit size 
>>>> as a
>>>> +       function pointer. This ensures that the function pointer can 
>>>> be fully
>>>> +       represented without truncation or corruption. The macro 
>>>> BUILD_BUG_ON is
>>>> +       integrated into xen/common/version.c to confirm conversion 
>>>> compatibility
>>>> +       across all target platforms.
>>>> +     - Tagged as `safe` for ECLAIR.
>>>
>>> Why the escaping of * here, when ...
>>>
>>>> --- a/docs/misra/rules.rst
>>>> +++ b/docs/misra/rules.rst
>>>> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>>>>       - All conversions to integer types are permitted if the 
>>>> destination
>>>>         type has enough bits to hold the entire value. Conversions to 
>>>> bool
>>>>         and void* are permitted. Conversions from 'void noreturn (*) 
>>>> (...)'
>>>> -       to 'void (*)(...)' are permitted.
>>>> +       to 'void (*)(...)' are permitted. Conversions from unsigned 
>>>> long or
>>>> +       (void \*) to a function pointer are permitted if the source 
>>>> type has
>>>> +       enough bits to restore function pointer without truncation or 
>>>> corruption.
>>>> +       Example::
>>>> +
>>>> +           unsigned long func_addr = (unsigned long)&some_function;
>>>> +           void (*restored_func)(void) = (void (*)(void))func_addr;
>>>
>>> ... context here suggests they work fine un-escaped, and you even add 
>>> some un-
>>> escaped instances as well. Perhaps I'm simply unaware of some 
>>> peculiarity?
>>>
>>
>> This is a literal rst block, while the other is not (* acts as a bullet 
>> point in rst iirc)
> 
> This is how "sphinx-build" tool interprets this.
> 1. * inside single quotes '' -> looks normal, e.g. ‘void (*)(…)’
> 2. * without quotes -> warning
> deviations.rst:369: WARNING: Inline emphasis start-string without 
> end-string. [docutils]
> 3. \* -> looks normal, e.g. (void *)
> 
> Because that we need such format: \*

Yet under "Example::" there's no quotation and no escaping. The one
"(void \*)" earlier in the text I'd suggest to replace by a quoted
form anyway, matching the rest of the text.

Jan

Re: [PATCH] misra: consider conversion from UL or (void*) to function pointer as safe
Posted by Jan Beulich 2 months, 1 week ago
On 21.08.2025 10:25, Nicola Vetrini wrote:
> On 2025-08-21 10:01, Jan Beulich wrote:
>> On 19.08.2025 20:55, Dmytro Prokopchuk1 wrote:
>>> Rule 11.1 states as following: "Conversions shall not be performed
>>> between a pointer to a function and any other type."
>>>
>>> The conversion from unsigned long or (void *) to a function pointer
>>> is safe in Xen because the architectures it supports (e.g., x86 and
>>> ARM) guarantee compatible representations between these types.
>>
>> I think we need to be as precise as possible here. The architectures
>> guarantee nothing, they only offer necessary fundamentals. In the
>> Windows x86 ABI, for example, you can't convert pointers to/from longs
>> without losing data. What we build upon is what respective ABIs say,
>> possibly in combination of implementation specifics left to compilers.
>>
> 
> +1, a mention of the compilers and targets this deviation relies upon is 
> needed.
> 
>>> --- a/docs/misra/deviations.rst
>>> +++ b/docs/misra/deviations.rst
>>> @@ -370,6 +370,16 @@ Deviations related to MISRA C:2012 Rules:
>>>         to store it.
>>>       - Tagged as `safe` for ECLAIR.
>>>
>>> +   * - R11.1
>>> +     - The conversion from unsigned long or (void \*) to a function 
>>> pointer does
>>> +       not lose any information or violate type safety assumptions if 
>>> unsigned
>>> +       long or (void \*) type is guaranteed to be the same bit size 
>>> as a
>>> +       function pointer. This ensures that the function pointer can 
>>> be fully
>>> +       represented without truncation or corruption. The macro 
>>> BUILD_BUG_ON is
>>> +       integrated into xen/common/version.c to confirm conversion 
>>> compatibility
>>> +       across all target platforms.
>>> +     - Tagged as `safe` for ECLAIR.
>>
>> Why the escaping of * here, when ...
>>
>>> --- a/docs/misra/rules.rst
>>> +++ b/docs/misra/rules.rst
>>> @@ -431,7 +431,13 @@ maintainers if you want to suggest a change.
>>>       - All conversions to integer types are permitted if the 
>>> destination
>>>         type has enough bits to hold the entire value. Conversions to 
>>> bool
>>>         and void* are permitted. Conversions from 'void noreturn 
>>> (*)(...)'
>>> -       to 'void (*)(...)' are permitted.
>>> +       to 'void (*)(...)' are permitted. Conversions from unsigned 
>>> long or
>>> +       (void \*) to a function pointer are permitted if the source 
>>> type has
>>> +       enough bits to restore function pointer without truncation or 
>>> corruption.
>>> +       Example::
>>> +
>>> +           unsigned long func_addr = (unsigned long)&some_function;
>>> +           void (*restored_func)(void) = (void (*)(void))func_addr;
>>
>> ... context here suggests they work fine un-escaped, and you even add 
>> some un-
>> escaped instances as well. Perhaps I'm simply unaware of some 
>> peculiarity?
> 
> This is a literal rst block, while the other is not (* acts as a bullet 
> point in rst iirc)

But everything here is bullet-pointed (with at least two levels)?

Jan