diff mbox series

[XEN,for-4.19,v2,1/1] xen: introduce a deviation for Rule 11.9

Message ID c684c36402e6740472fa91d73436ca5790e5e109.1696948320.git.nicola.vetrini@bugseng.com (mailing list archive)
State New, archived
Headers show
Series address violations of MISRA C:2012 Rule 11.9 | expand

Commit Message

Nicola Vetrini Oct. 11, 2023, 12:46 p.m. UTC
The constant 0 is used instead of NULL in '__ACCESS_ONCE' as a
compile-time check to detect non-scalar types; its usage for this
purpose is deviated.

Furthermore, the 'access_field' and 'typeof_field' macros are
introduced as a general way to deal with accesses to structs
without declaring a struct variable.

No functional change intended.

Signed-off-by: Nicola Vetrini <nicola.vetrini@bugseng.com>
---
Changes in v2:
- added entry in deviations.rst
---
 automation/eclair_analysis/ECLAIR/deviations.ecl | 9 +++++++++
 docs/misra/deviations.rst                        | 5 +++++
 xen/include/xen/compiler.h                       | 5 ++++-
 xen/include/xen/kernel.h                         | 2 +-
 4 files changed, 19 insertions(+), 2 deletions(-)

Comments

Andrew Cooper Oct. 11, 2023, 4:56 p.m. UTC | #1
On 11/10/2023 8:46 pm, Nicola Vetrini wrote:
> diff --git a/docs/misra/deviations.rst b/docs/misra/deviations.rst
> index ee7aed0609d2..1b00e4e3e9b7 100644
> --- a/docs/misra/deviations.rst
> +++ b/docs/misra/deviations.rst
> @@ -199,6 +199,11 @@ Deviations related to MISRA C:2012 Rules:
>         See automation/eclair_analysis/deviations.ecl for the full explanation.
>       - Tagged as `safe` for ECLAIR.
>  
> +   * - R11.9
> +     - __ACCESS_ONCE uses a 0 as a null pointer constant to check if a type is
> +       scalar, therefore its usage for this purpose is allowed.
> +     - Tagged as `deliberate` for ECLAIR.

Really?

#define __ACCESS_ONCE(x)
    (void)(typeof(x))0; /* Scalar typecheck. */

That's not a pointer.

If someone were to pass in an x who's type was pointer-to-object, then
yes it is technically a NULL pointer constant for long enough for the
build to error out.

What justification is Eclair using to suggest that it is a pointer?

If you really really want to shut things up, it doesn't need to be 0 -
it could be 1 or any other integer, but this honestly feels like a bug
in Eclair to me.

~Andrew
Nicola Vetrini Oct. 12, 2023, 12:27 p.m. UTC | #2
On 11/10/2023 18:56, andrew.cooper3@citrix.com wrote:
> On 11/10/2023 8:46 pm, Nicola Vetrini wrote:
>> diff --git a/docs/misra/deviations.rst b/docs/misra/deviations.rst
>> index ee7aed0609d2..1b00e4e3e9b7 100644
>> --- a/docs/misra/deviations.rst
>> +++ b/docs/misra/deviations.rst
>> @@ -199,6 +199,11 @@ Deviations related to MISRA C:2012 Rules:
>>         See automation/eclair_analysis/deviations.ecl for the full 
>> explanation.
>>       - Tagged as `safe` for ECLAIR.
>> 
>> +   * - R11.9
>> +     - __ACCESS_ONCE uses a 0 as a null pointer constant to check if 
>> a type is
>> +       scalar, therefore its usage for this purpose is allowed.
>> +     - Tagged as `deliberate` for ECLAIR.
> 
> Really?
> 
> #define __ACCESS_ONCE(x)
>     (void)(typeof(x))0; /* Scalar typecheck. */
> 
> That's not a pointer.
> 
> If someone were to pass in an x who's type was pointer-to-object, then
> yes it is technically a NULL pointer constant for long enough for the
> build to error out.
> 
> What justification is Eclair using to suggest that it is a pointer?
> 
> If you really really want to shut things up, it doesn't need to be 0 -
> it could be 1 or any other integer, but this honestly feels like a bug
> in Eclair to me.
> 
> ~Andrew

The non-compliant uses found by the checker were due to function 
pointers
e.g.

void (*fp)(int i);

violation for rule MC3R1.R11.9: (required) The macro `NULL' shall be the 
only permitted form of integer null pointer constant. (untagged)
p.c:12.3-12.7: (MACRO) Loc #1 [culprit: non-compliant use of null 
pointer constant]
   A(fp) = NULL;
   <~~~>
p.c:6.8-6.19: for #1 [culprit: expanded from macro `_A']
  (void)(typeof(X))0; \
        <~~~~~~~~~~>
p.c:9.16-9.20: for #1 [culprit: expanded from macro `A']
#define A(X) (*_A(X))
                <~~~>

These uses do not cause a build fail, and we deemed this usage of 0 to 
be correct
(a neutral value that would allow __ACCESS_ONCE to support any type of 
argument).
While perhaps some other value does have the same property (e.g., 1), we 
felt that it was
okay to let 0 remain there.
Stefano Stabellini Oct. 12, 2023, 11:24 p.m. UTC | #3
On Wed, 11 Oct 2023, Nicola Vetrini wrote:
> The constant 0 is used instead of NULL in '__ACCESS_ONCE' as a
> compile-time check to detect non-scalar types; its usage for this
> purpose is deviated.
> 
> Furthermore, the 'access_field' and 'typeof_field' macros are
> introduced as a general way to deal with accesses to structs
> without declaring a struct variable.
> 
> No functional change intended.
> 
> Signed-off-by: Nicola Vetrini <nicola.vetrini@bugseng.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


> ---
> Changes in v2:
> - added entry in deviations.rst
> ---
>  automation/eclair_analysis/ECLAIR/deviations.ecl | 9 +++++++++
>  docs/misra/deviations.rst                        | 5 +++++
>  xen/include/xen/compiler.h                       | 5 ++++-
>  xen/include/xen/kernel.h                         | 2 +-
>  4 files changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/automation/eclair_analysis/ECLAIR/deviations.ecl b/automation/eclair_analysis/ECLAIR/deviations.ecl
> index fa56e5c00a27..28d9c37bedb2 100644
> --- a/automation/eclair_analysis/ECLAIR/deviations.ecl
> +++ b/automation/eclair_analysis/ECLAIR/deviations.ecl
> @@ -246,6 +246,15 @@ constant expressions are required.\""
>    "any()"}
>  -doc_end
>  
> +#
> +# Series 11
> +#
> +
> +-doc_begin="This construct is used to check if the type is scalar, and for this purpose the use of 0 as a null pointer constant is deliberate."
> +-config=MC3R1.R11.9,reports+={deliberate, "any_area(any_loc(any_exp(macro(^__ACCESS_ONCE$))))"
> +}
> +-doc_end
> +
>  #
>  # Series 13
>  #
> diff --git a/docs/misra/deviations.rst b/docs/misra/deviations.rst
> index ee7aed0609d2..1b00e4e3e9b7 100644
> --- a/docs/misra/deviations.rst
> +++ b/docs/misra/deviations.rst
> @@ -199,6 +199,11 @@ Deviations related to MISRA C:2012 Rules:
>         See automation/eclair_analysis/deviations.ecl for the full explanation.
>       - Tagged as `safe` for ECLAIR.
>  
> +   * - R11.9
> +     - __ACCESS_ONCE uses a 0 as a null pointer constant to check if a type is
> +       scalar, therefore its usage for this purpose is allowed.
> +     - Tagged as `deliberate` for ECLAIR.
> +
>     * - R13.5
>       - All developers and reviewers can be safely assumed to be well aware of
>         the short-circuit evaluation strategy for logical operators.
> diff --git a/xen/include/xen/compiler.h b/xen/include/xen/compiler.h
> index dd99e573083f..15be9a750b23 100644
> --- a/xen/include/xen/compiler.h
> +++ b/xen/include/xen/compiler.h
> @@ -109,13 +109,16 @@
>  
>  #define offsetof(a,b) __builtin_offsetof(a,b)
>  
> +/* Access the field of structure type, without defining a local variable */
> +#define access_field(type, member) (((type *)NULL)->member)
> +#define typeof_field(type, member) typeof(access_field(type, member))
>  /**
>   * sizeof_field(TYPE, MEMBER)
>   *
>   * @TYPE: The structure containing the field of interest
>   * @MEMBER: The field to return the size of
>   */
> -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
> +#define sizeof_field(TYPE, MEMBER) sizeof(access_field(TYPE, MEMBER))
>  
>  #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
>  #define alignof __alignof__
> diff --git a/xen/include/xen/kernel.h b/xen/include/xen/kernel.h
> index 46b3c9c02625..2c5ed7736c99 100644
> --- a/xen/include/xen/kernel.h
> +++ b/xen/include/xen/kernel.h
> @@ -51,7 +51,7 @@
>   *
>   */
>  #define container_of(ptr, type, member) ({                      \
> -        typeof( ((type *)0)->member ) *__mptr = (ptr);          \
> +        typeof_field(type, member) *__mptr = (ptr);             \
>          (type *)( (char *)__mptr - offsetof(type,member) );})
>  
>  /*
> -- 
> 2.34.1
>
Jan Beulich Oct. 16, 2023, 1:43 p.m. UTC | #4
On 11.10.2023 14:46, Nicola Vetrini wrote:
> --- a/xen/include/xen/compiler.h
> +++ b/xen/include/xen/compiler.h
> @@ -109,13 +109,16 @@
>  
>  #define offsetof(a,b) __builtin_offsetof(a,b)
>  
> +/* Access the field of structure type, without defining a local variable */
> +#define access_field(type, member) (((type *)NULL)->member)

This is not a field access, so I consider the macro misnamed. Question is
whether such a helper macro is needed in the first place.

> +#define typeof_field(type, member) typeof(access_field(type, member))

If this needs adding, it wants to come ...

>  /**
>   * sizeof_field(TYPE, MEMBER)
>   *
>   * @TYPE: The structure containing the field of interest
>   * @MEMBER: The field to return the size of
>   */
> -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
> +#define sizeof_field(TYPE, MEMBER) sizeof(access_field(TYPE, MEMBER))

... with a commend similar as this one has. (Or the commend could be
slightly altered to cover both).

Further, if fiddling with these: Wouldn't they better move to macros.h?

Jan
Jan Beulich Oct. 16, 2023, 1:46 p.m. UTC | #5
On 11.10.2023 18:56, andrew.cooper3@citrix.com wrote:
> On 11/10/2023 8:46 pm, Nicola Vetrini wrote:
>> diff --git a/docs/misra/deviations.rst b/docs/misra/deviations.rst
>> index ee7aed0609d2..1b00e4e3e9b7 100644
>> --- a/docs/misra/deviations.rst
>> +++ b/docs/misra/deviations.rst
>> @@ -199,6 +199,11 @@ Deviations related to MISRA C:2012 Rules:
>>         See automation/eclair_analysis/deviations.ecl for the full explanation.
>>       - Tagged as `safe` for ECLAIR.
>>  
>> +   * - R11.9
>> +     - __ACCESS_ONCE uses a 0 as a null pointer constant to check if a type is
>> +       scalar, therefore its usage for this purpose is allowed.
>> +     - Tagged as `deliberate` for ECLAIR.
> 
> Really?
> 
> #define __ACCESS_ONCE(x)
>     (void)(typeof(x))0; /* Scalar typecheck. */
> 
> That's not a pointer.
> 
> If someone were to pass in an x who's type was pointer-to-object, then
> yes it is technically a NULL pointer constant for long enough for the
> build to error out.

Why would it error out? ACCESS_ONCE() on a variable of pointer type is
as okay as one on a variable of (some kind of) integer type. (Sadly the
check as is would even let floating point types pass. At the same time
the check is too strict to allow e.g. single-machine-word struct/union
to also pass.)

Jan
Nicola Vetrini Oct. 16, 2023, 4:49 p.m. UTC | #6
On 16/10/2023 15:43, Jan Beulich wrote:
> On 11.10.2023 14:46, Nicola Vetrini wrote:
>> --- a/xen/include/xen/compiler.h
>> +++ b/xen/include/xen/compiler.h
>> @@ -109,13 +109,16 @@
>> 
>>  #define offsetof(a,b) __builtin_offsetof(a,b)
>> 
>> +/* Access the field of structure type, without defining a local 
>> variable */
>> +#define access_field(type, member) (((type *)NULL)->member)
> 
> This is not a field access, so I consider the macro misnamed. Question 
> is
> whether such a helper macro is needed in the first place.
> 
>> +#define typeof_field(type, member) typeof(access_field(type, member))
> 
> If this needs adding, it wants to come ...
> 
>>  /**
>>   * sizeof_field(TYPE, MEMBER)
>>   *
>>   * @TYPE: The structure containing the field of interest
>>   * @MEMBER: The field to return the size of
>>   */
>> -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
>> +#define sizeof_field(TYPE, MEMBER) sizeof(access_field(TYPE, MEMBER))
> 
> ... with a commend similar as this one has. (Or the commend could be
> slightly altered to cover both).
> 

I added access_field since it's possibly useful on its own in the 
future,
but that may not be the case. Not a real field access, perhaps a 
fake_access_field?
Ok about the missing comment for typeof_field.

> Further, if fiddling with these: Wouldn't they better move to macros.h?
> 
> Jan

That seems a good suggestion, as they are not compiler-specific.
Jan Beulich Oct. 17, 2023, 6:51 a.m. UTC | #7
On 16.10.2023 18:49, Nicola Vetrini wrote:
> On 16/10/2023 15:43, Jan Beulich wrote:
>> On 11.10.2023 14:46, Nicola Vetrini wrote:
>>> --- a/xen/include/xen/compiler.h
>>> +++ b/xen/include/xen/compiler.h
>>> @@ -109,13 +109,16 @@
>>>
>>>  #define offsetof(a,b) __builtin_offsetof(a,b)
>>>
>>> +/* Access the field of structure type, without defining a local 
>>> variable */
>>> +#define access_field(type, member) (((type *)NULL)->member)
>>
>> This is not a field access, so I consider the macro misnamed. Question 
>> is
>> whether such a helper macro is needed in the first place.
>>
>>> +#define typeof_field(type, member) typeof(access_field(type, member))
>>
>> If this needs adding, it wants to come ...
>>
>>>  /**
>>>   * sizeof_field(TYPE, MEMBER)
>>>   *
>>>   * @TYPE: The structure containing the field of interest
>>>   * @MEMBER: The field to return the size of
>>>   */
>>> -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
>>> +#define sizeof_field(TYPE, MEMBER) sizeof(access_field(TYPE, MEMBER))
>>
>> ... with a commend similar as this one has. (Or the commend could be
>> slightly altered to cover both).
>>
> 
> I added access_field since it's possibly useful on its own in the 
> future,
> but that may not be the case. Not a real field access, perhaps a 
> fake_access_field?

I don't like this either, I'm afraid: This isn't a fake access. Maybe
field_of() or field_of_type()? Yet at this point I'd still prefer for
this to not be a separate macro in the first place.

Jan
Nicola Vetrini Oct. 17, 2023, 8:16 a.m. UTC | #8
On 17/10/2023 08:51, Jan Beulich wrote:
> On 16.10.2023 18:49, Nicola Vetrini wrote:
>> On 16/10/2023 15:43, Jan Beulich wrote:
>>> On 11.10.2023 14:46, Nicola Vetrini wrote:
>>>> --- a/xen/include/xen/compiler.h
>>>> +++ b/xen/include/xen/compiler.h
>>>> @@ -109,13 +109,16 @@
>>>> 
>>>>  #define offsetof(a,b) __builtin_offsetof(a,b)
>>>> 
>>>> +/* Access the field of structure type, without defining a local
>>>> variable */
>>>> +#define access_field(type, member) (((type *)NULL)->member)
>>> 
>>> This is not a field access, so I consider the macro misnamed. 
>>> Question
>>> is
>>> whether such a helper macro is needed in the first place.
>>> 
>>>> +#define typeof_field(type, member) typeof(access_field(type, 
>>>> member))
>>> 
>>> If this needs adding, it wants to come ...
>>> 
>>>>  /**
>>>>   * sizeof_field(TYPE, MEMBER)
>>>>   *
>>>>   * @TYPE: The structure containing the field of interest
>>>>   * @MEMBER: The field to return the size of
>>>>   */
>>>> -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
>>>> +#define sizeof_field(TYPE, MEMBER) sizeof(access_field(TYPE, 
>>>> MEMBER))
>>> 
>>> ... with a commend similar as this one has. (Or the commend could be
>>> slightly altered to cover both).
>>> 
>> 
>> I added access_field since it's possibly useful on its own in the
>> future,
>> but that may not be the case. Not a real field access, perhaps a
>> fake_access_field?
> 
> I don't like this either, I'm afraid: This isn't a fake access. Maybe
> field_of() or field_of_type()? Yet at this point I'd still prefer for
> this to not be a separate macro in the first place.
> 
> Jan

Ok, no problem.
diff mbox series

Patch

diff --git a/automation/eclair_analysis/ECLAIR/deviations.ecl b/automation/eclair_analysis/ECLAIR/deviations.ecl
index fa56e5c00a27..28d9c37bedb2 100644
--- a/automation/eclair_analysis/ECLAIR/deviations.ecl
+++ b/automation/eclair_analysis/ECLAIR/deviations.ecl
@@ -246,6 +246,15 @@  constant expressions are required.\""
   "any()"}
 -doc_end
 
+#
+# Series 11
+#
+
+-doc_begin="This construct is used to check if the type is scalar, and for this purpose the use of 0 as a null pointer constant is deliberate."
+-config=MC3R1.R11.9,reports+={deliberate, "any_area(any_loc(any_exp(macro(^__ACCESS_ONCE$))))"
+}
+-doc_end
+
 #
 # Series 13
 #
diff --git a/docs/misra/deviations.rst b/docs/misra/deviations.rst
index ee7aed0609d2..1b00e4e3e9b7 100644
--- a/docs/misra/deviations.rst
+++ b/docs/misra/deviations.rst
@@ -199,6 +199,11 @@  Deviations related to MISRA C:2012 Rules:
        See automation/eclair_analysis/deviations.ecl for the full explanation.
      - Tagged as `safe` for ECLAIR.
 
+   * - R11.9
+     - __ACCESS_ONCE uses a 0 as a null pointer constant to check if a type is
+       scalar, therefore its usage for this purpose is allowed.
+     - Tagged as `deliberate` for ECLAIR.
+
    * - R13.5
      - All developers and reviewers can be safely assumed to be well aware of
        the short-circuit evaluation strategy for logical operators.
diff --git a/xen/include/xen/compiler.h b/xen/include/xen/compiler.h
index dd99e573083f..15be9a750b23 100644
--- a/xen/include/xen/compiler.h
+++ b/xen/include/xen/compiler.h
@@ -109,13 +109,16 @@ 
 
 #define offsetof(a,b) __builtin_offsetof(a,b)
 
+/* Access the field of structure type, without defining a local variable */
+#define access_field(type, member) (((type *)NULL)->member)
+#define typeof_field(type, member) typeof(access_field(type, member))
 /**
  * sizeof_field(TYPE, MEMBER)
  *
  * @TYPE: The structure containing the field of interest
  * @MEMBER: The field to return the size of
  */
-#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
+#define sizeof_field(TYPE, MEMBER) sizeof(access_field(TYPE, MEMBER))
 
 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
 #define alignof __alignof__
diff --git a/xen/include/xen/kernel.h b/xen/include/xen/kernel.h
index 46b3c9c02625..2c5ed7736c99 100644
--- a/xen/include/xen/kernel.h
+++ b/xen/include/xen/kernel.h
@@ -51,7 +51,7 @@ 
  *
  */
 #define container_of(ptr, type, member) ({                      \
-        typeof( ((type *)0)->member ) *__mptr = (ptr);          \
+        typeof_field(type, member) *__mptr = (ptr);             \
         (type *)( (char *)__mptr - offsetof(type,member) );})
 
 /*