develop/tools/coccinelle.html · develop/tools/coccinelle.rst 공식 원문 ↗

Zephyr 3.7.0 · Develop · Tools · Coccinelle

Coccinelle semantic patch

Semantic patch로 Zephyr source tree의 반복 pattern을 찾고 report하거나 검토 가능한 수정안을 생성합니다.

Official pathdevelop/tools/coccinelle.html
Source filedevelop/tools/coccinelle.rst
Source versionZephyr 3.7.0
TranslationFull · reviewed

본문 기준: Zephyr 3.7.0 LTS3 · 이후 유지보수 패치는 별도입니다.

Part 1

요약·해설

Coccinelle 설치와 version 조건, coccicheck의 report·patch·context·org mode, 병렬화·범위·debug·index option, 새 SmPL script 작성 규칙과 ARRAY_SIZE 예제를 설명합니다.

Modes

report · patch · context · org

Scale

parallel · index · directory

SmPL

rule · Python · confidence

Part 2

접을 수 있는 영어 원문 전체

영어 원문 전체 펼치기
원문 SHA-256 9EAB6FEF394FC3B0D3AB5491198326A84B6AE6BDB056C8B19203555D3A381DBB
.. _coccinelle:

..
   Copyright 2010 Nicolas Palix <[email protected]>
   Copyright 2010 Julia Lawall <[email protected]>
   Copyright 2010 Gilles Muller <[email protected]>

Coccinelle
##########

Coccinelle is a tool for pattern matching and text transformation that has
many uses in kernel development, including the application of complex,
tree-wide patches and detection of problematic programming patterns.

.. note::
   Linux and macOS development environments are supported, but not Windows.

Getting Coccinelle
******************

The semantic patches included in the kernel use features and options
which are provided by Coccinelle version 1.0.0-rc11 and above.
Using earlier versions will fail as the option names used by
the Coccinelle files and ``coccicheck`` have been updated.

Coccinelle is available through the package manager
of many distributions, e.g. :

.. rst-class:: rst-columns

   * Debian
   * Fedora
   * Ubuntu
   * OpenSUSE
   * Arch Linux
   * NetBSD
   * FreeBSD

Some distribution packages are obsolete and it is recommended
to use the latest version released from the Coccinelle homepage at
http://coccinelle.lip6.fr/

Or from Github at:

https://github.com/coccinelle/coccinelle

Once you have it, run the following commands:

.. code-block:: console

   ./autogen
   ./configure
   make

as a regular user, and install it with:

.. code-block:: console

   sudo make install

More detailed installation instructions to build from source can be
found at:

https://github.com/coccinelle/coccinelle/blob/master/install.txt

Supplemental documentation
**************************

For Semantic Patch Language(SmPL) grammar documentation refer to:

https://coccinelle.gitlabpages.inria.fr/website/documentation.html

Using Coccinelle on Zephyr
**************************

``coccicheck`` checker is the front-end to the Coccinelle infrastructure
and has various modes:

Four basic modes are defined: ``patch``, ``report``, ``context``, and
``org``. The mode to use is specified by setting ``--mode=<mode>`` or
``-m=<mode>``.

* ``patch`` proposes a fix, when possible.

* ``report`` generates a list in the following format:
  file:line:column-column: message

* ``context`` highlights lines of interest and their context in a
  diff-like style.Lines of interest are indicated with ``-``.

* ``org`` generates a report in the Org mode format of Emacs.

Note that not all semantic patches implement all modes. For easy use
of Coccinelle, the default mode is ``report``.

Two other modes provide some common combinations of these modes.

- ``chain`` tries the previous modes in the order above until one succeeds.

- ``rep+ctxt`` runs successively the report mode and the context mode.
  It should be used with the C option (described later)
  which checks the code on a file basis.

Examples
********

To make a report for every semantic patch, run the following command:

.. code-block:: console

   ./scripts/coccicheck --mode=report

To produce patches, run:

.. code-block:: console

   ./scripts/coccicheck --mode=patch

The ``coccicheck`` target applies every semantic patch available in the
sub-directories of ``scripts/coccinelle`` to the entire source code tree.

For each semantic patch, a commit message is proposed.  It gives a
description of the problem being checked by the semantic patch, and
includes a reference to Coccinelle.

As any static code analyzer, Coccinelle produces false
positives. Thus, reports must be carefully checked, and patches reviewed.

To enable verbose messages set ``--verbose=1`` option, for example:

.. code-block:: console

   ./scripts/coccicheck --mode=report --verbose=1

Coccinelle parallelization
**************************

By default, ``coccicheck`` tries to run as parallel as possible. To change
the parallelism, set the ``--jobs=<number>`` option. For example, to run
across 4 CPUs:

.. code-block:: console

   ./scripts/coccicheck --mode=report --jobs=4

As of Coccinelle 1.0.2 Coccinelle uses Ocaml parmap for parallelization,
if support for this is detected you will benefit from parmap parallelization.

When parmap is enabled ``coccicheck`` will enable dynamic load balancing by using
``--chunksize 1`` argument, this ensures we keep feeding threads with work
one by one, so that we avoid the situation where most work gets done by only
a few threads. With dynamic load balancing, if a thread finishes early we keep
feeding it more work.

When parmap is enabled, if an error occurs in Coccinelle, this error
value is propagated back, the return value of the ``coccicheck``
command captures this return value.

Using Coccinelle with a single semantic patch
*********************************************

The option ``--cocci`` can be used to check a single
semantic patch. In that case, the variable must be initialized with
the name of the semantic patch to apply.

For instance:

.. code-block:: console

   ./scripts/coccicheck --mode=report --cocci=<example.cocci>

or:

.. code-block:: console

   ./scripts/coccicheck --mode=report --cocci=./path/to/<example.cocci>


Controlling which files are processed by Coccinelle
***************************************************

By default the entire source tree is checked.

To apply Coccinelle to a specific directory, pass the path of specific
directory as an argument.

For example, to check ``drivers/usb/`` one may write:

.. code-block:: console

   ./scripts/coccicheck --mode=patch drivers/usb/

The ``report`` mode is the default. You can select another one with the
``--mode=<mode>`` option explained above.

Debugging Coccinelle SmPL patches
*********************************

Using ``coccicheck`` is best as it provides in the spatch command line
include options matching the options used when we compile the kernel.
You can learn what these options are by using verbose option, you could
then manually run Coccinelle with debug options added.

Alternatively you can debug running Coccinelle against SmPL patches
by asking for stderr to be redirected to stderr, by default stderr
is redirected to /dev/null, if you'd like to capture stderr you
can specify the ``--debug=file.err`` option to ``coccicheck``. For
instance:

.. code-block:: console

   rm -f cocci.err
   ./scripts/coccicheck --mode=patch --debug=cocci.err
   cat cocci.err

Debugging support is only supported when using Coccinelle >= 1.0.2.

Additional Flags
****************

Additional flags can be passed to spatch through the SPFLAGS
variable. This works as Coccinelle respects the last flags
given to it when options are in conflict.

.. code-block:: console

   ./scripts/coccicheck --sp-flag="--use-glimpse"

Coccinelle supports idutils as well but requires coccinelle >= 1.0.6.
When no ID file is specified coccinelle assumes your ID database file
is in the file .id-utils.index on the top level of the kernel, coccinelle
carries a script scripts/idutils_index.sh which creates the database with:

.. code-block:: console

   mkid -i C --output .id-utils.index

If you have another database filename you can also just symlink with this
name.

.. code-block:: console

   ./scripts/coccicheck --sp-flag="--use-idutils"

Alternatively you can specify the database filename explicitly, for
instance:

.. code-block:: console

   ./scripts/coccicheck --sp-flag="--use-idutils /full-path/to/ID"

Sometimes coccinelle doesn't recognize or parse complex macro variables
due to insufficient definition. Therefore, to make it parsable we
explicitly provide the prototype of the complex macro using the
``---macro-file-builtins <headerfile.h>`` flag.

The ``<headerfile.h>`` should contain the complete prototype of
the complex macro from which spatch engine can extract the type
information required during transformation.

For example:

``Z_SYSCALL_HANDLER`` is not recognized by coccinelle. Therefore, we
put its prototype in a header file, say for example ``mymacros.h``.

.. code-block:: console

   $ cat mymacros.h
   #define Z_SYSCALL_HANDLER int xxx

Now we pass the header file ``mymacros.h`` during transformation:

.. code-block:: console

   ./scripts/coccicheck --sp-flag="---macro-file-builtins mymacros.h"

See ``spatch --help`` to learn more about spatch options.

Note that the ``--use-glimpse`` and ``--use-idutils`` options
require external tools for indexing the code. None of them is
thus active by default. However, by indexing the code with
one of these tools, and according to the cocci file used,
spatch could proceed the entire code base more quickly.


SmPL patch specific options
***************************

SmPL patches can have their own requirements for options passed
to Coccinelle. SmPL patch specific options can be provided by
providing them at the top of the SmPL patch, for instance:

.. code-block:: console

   // Options: --no-includes --include-headers

Proposing new semantic patches
******************************

New semantic patches can be proposed and submitted by kernel
developers. For sake of clarity, they should be organized in the
sub-directories of ``scripts/coccinelle/``.

The cocci script should have the following properties:

* The script **must** have ``report`` mode.

* The first few lines should state the purpose of the script
  using ``///`` comments . Usually, this message would be used as the
  commit log when proposing a patch based on the script.

Example
=======

.. code-block:: console

   /// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element

* A more detailed information about the script with exceptional cases
  or false positives (if any) can be listed using ``//#`` comments.

Example
=======

.. code-block:: console

   //# This makes an effort to find cases where ARRAY_SIZE can be used such as
   //# where there is a division of sizeof the array by the sizeof its first
   //# element or by any indexed element or the element type. It replaces the
   //# division of the two sizeofs by ARRAY_SIZE.

* Confidence: It is a property defined to specify the accuracy level of
  the script. It can be either ``High``, ``Moderate`` or ``Low`` depending
  upon the number of false positives observed.

Example
=======

.. code-block:: console

   // Confidence: High

* Virtual rules: These are required to support the various modes framed
  in the script. The virtual rule specified in the script should have
  the corresponding mode handling rule.

Example
=======

.. code-block:: console

   virtual context

   @depends on context@
   type T;
   T[] E;
   @@
   (
   * (sizeof(E)/sizeof(*E))
   |
   * (sizeof(E)/sizeof(E[...]))
   |
   * (sizeof(E)/sizeof(T))
   )

Detailed description of the ``report`` mode
*******************************************

``report`` generates a list in the following format:

.. code-block:: console

   file:line:column-column: message

Example
=======

Running:

.. code-block:: console

   ./scripts/coccicheck --mode=report --cocci=scripts/coccinelle/array_size.cocci

will execute the following part of the SmPL script:

.. code-block:: console

   <smpl>

   @r depends on (org || report)@
   type T;
   T[] E;
   position p;
   @@
   (
   (sizeof(E)@p /sizeof(*E))
   |
   (sizeof(E)@p /sizeof(E[...]))
   |
   (sizeof(E)@p /sizeof(T))
   )

   @script:python depends on report@
   p << r.p;
   @@

   msg="WARNING: Use ARRAY_SIZE"
   coccilib.report.print_report(p[0], msg)

   </smpl>

This SmPL excerpt generates entries on the standard output, as
illustrated below:

.. code-block:: console

   ext/hal/nxp/mcux/drivers/lpc/fsl_wwdt.c:66:49-50: WARNING: Use ARRAY_SIZE
   ext/hal/nxp/mcux/drivers/lpc/fsl_ctimer.c:74:53-54: WARNING: Use ARRAY_SIZE
   ext/hal/nxp/mcux/drivers/imx/fsl_dcp.c:944:45-46: WARNING: Use ARRAY_SIZE


Detailed description of the ``patch`` mode
******************************************

When the ``patch`` mode is available, it proposes a fix for each problem
identified.

Example
=======

Running:

.. code-block:: console

   ./scripts/coccicheck --mode=patch --cocci=scripts/coccinelle/misc/array_size.cocci

will execute the following part of the SmPL script:

.. code-block:: console

   <smpl>

   @depends on patch@
   type T;
   T[] E;
   @@
   (
   - (sizeof(E)/sizeof(*E))
   + ARRAY_SIZE(E)
   |
   - (sizeof(E)/sizeof(E[...]))
   + ARRAY_SIZE(E)
   |
   - (sizeof(E)/sizeof(T))
   + ARRAY_SIZE(E)
   )

   </smpl>

This SmPL excerpt generates patch hunks on the standard output, as
illustrated below:

.. code-block:: console

   diff -u -p a/ext/lib/encoding/tinycbor/src/cborvalidation.c b/ext/lib/encoding/tinycbor/src/cborvalidation.c
   --- a/ext/lib/encoding/tinycbor/src/cborvalidation.c
   +++ b/ext/lib/encoding/tinycbor/src/cborvalidation.c
   @@ -325,7 +325,7 @@ static inline CborError validate_number(
   static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int recursionLeft)
   {
     CborType type = cbor_value_get_type(it);
   -    const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
   +    const size_t knownTagCount = ARRAY_SIZE(knownTagData);
      const struct KnownTagData *tagData = knownTagData;
      const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount;

Detailed description of the ``context`` mode
********************************************

``context`` highlights lines of interest and their context
in a diff-like style.

.. note::
 The diff-like output generated is NOT an applicable patch. The
 intent of the ``context`` mode is to highlight the important lines
 (annotated with minus, ``-``) and gives some surrounding context
 lines around. This output can be used with the diff mode of
 Emacs to review the code.

Example
=======

Running:

.. code-block:: console

   ./scripts/coccicheck --mode=context --cocci=scripts/coccinelle/array_size.cocci

will execute the following part of the SmPL script:

.. code-block:: console

   <smpl>

   @depends on context@
   type T;
   T[] E;
   @@
   (
   * (sizeof(E)/sizeof(*E))
   |
   * (sizeof(E)/sizeof(E[...]))
   |
   * (sizeof(E)/sizeof(T))
   )

   </smpl>

This SmPL excerpt generates diff hunks on the standard output, as
illustrated below:

.. code-block:: console

   diff -u -p ext/lib/encoding/tinycbor/src/cborvalidation.c /tmp/nothing/ext/lib/encoding/tinycbor/src/cborvalidation.c
   --- ext/lib/encoding/tinycbor/src/cborvalidation.c
   +++ /tmp/nothing/ext/lib/encoding/tinycbor/src/cborvalidation.c
   @@ -325,7 +325,6 @@ static inline CborError validate_number(
   static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int recursionLeft)
   {
     CborType type = cbor_value_get_type(it);
   -    const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
      const struct KnownTagData *tagData = knownTagData;
      const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount;

Detailed description of the ``org`` mode
****************************************

``org`` generates a report in the Org mode format of Emacs.

Example
=======

Running:

.. code-block:: console

   ./scripts/coccicheck --mode=org --cocci=scripts/coccinelle/misc/array_size.cocci

will execute the following part of the SmPL script:

.. code-block:: console

   <smpl>

   @r depends on (org || report)@
   type T;
   T[] E;
   position p;
   @@
   (
   (sizeof(E)@p /sizeof(*E))
   |
   (sizeof(E)@p /sizeof(E[...]))
   |
   (sizeof(E)@p /sizeof(T))
   )

   @script:python depends on org@
   p << r.p;
   @@
   coccilib.org.print_todo(p[0], "WARNING should use ARRAY_SIZE")

   </smpl>

This SmPL excerpt generates Org entries on the standard output, as
illustrated below:

.. code-block:: console

   * TODO [[view:ext/lib/encoding/tinycbor/src/cborvalidation.c::face=ovl-face1::linb=328::colb=52::cole=53][WARNING should use ARRAY_SIZE]]

Coccinelle Mailing List
***********************

Subscribe to the coccinelle mailing list:

* https://systeme.lip6.fr/mailman/listinfo/cocci

Archives:

* https://lore.kernel.org/cocci/
* https://systeme.lip6.fr/pipermail/cocci/

Part 3

한국어 전문 번역

Coccinelle

Coccinelle은 pattern matching과 text transformation 도구입니다. Kernel 개발에서는 복잡한 tree-wide patch를 적용하거나 문제가 되는 programming pattern을 탐지하는 데 사용합니다.

Coccinelle 설치

coccicheck와 kernel에 포함된 semantic patch는 Coccinelle 1.0.0-rc11 이상에서 제공하는 기능과 option을 사용합니다. 그보다 오래된 version은 Coccinelle file과 coccicheck의 option 이름이 바뀌었기 때문에 실패합니다.

Coccinelle은 다음 distribution의 package manager로 설치할 수 있습니다.

  • Debian
  • Fedora
  • Ubuntu
  • OpenSUSE
  • Arch Linux
  • NetBSD
  • FreeBSD

일부 distribution package는 오래되었으므로 최신 release가 필요하면 Coccinelle homepage 또는 GitHub repository를 사용합니다.

Source를 받은 뒤 일반 사용자로 다음 명령을 실행합니다.

./autogen
./configure
make

Build가 끝나면 다음 명령으로 system에 설치합니다.

sudo make install

자세한 source build 절차는 Coccinelle install.txt에 있습니다.

보충 문서

Semantic Patch Language(SmPL) 문법은 Coccinelle documentation을 참고합니다.

Zephyr에서 Coccinelle 사용

coccicheck는 Coccinelle infrastructure의 front-end이며 --mode=<mode> 또는 -m=<mode>로 실행 mode를 선택합니다.

  • patch: 가능한 경우 수정 patch를 제안합니다.
  • report: file:line:column-column: message 형식의 문제 목록을 만듭니다.
  • context: 관심 line과 주변 문맥을 diff와 비슷하게 표시하며 관심 line에는 -를 붙입니다.
  • org: Emacs Org mode 형식으로 report를 만듭니다.

모든 semantic patch가 모든 mode를 구현하는 것은 아닙니다. 기본 mode는 사용하기 쉬운 report입니다.

두 결합 mode도 있습니다.

  • chain: 위 네 mode를 순서대로 시도하여 하나가 성공할 때까지 진행합니다.
  • rep+ctxt: report와 context를 연달아 실행합니다. File 단위로 code를 검사하는 C option과 함께 사용해야 합니다.

기본 실행 예

모든 semantic patch에 대해 report를 만들려면:

./scripts/coccicheck --mode=report

수정 patch를 만들려면:

./scripts/coccicheck --mode=patch

coccicheck target은 scripts/coccinelle 하위 directory의 모든 semantic patch를 source tree 전체에 적용합니다.

각 semantic patch에는 검사하는 문제를 설명하고 Coccinelle reference를 포함한 commit message도 제안됩니다.

--verbose=1로 자세한 message를 활성화할 수 있습니다.

./scripts/coccicheck --mode=report --verbose=1

Coccinelle 병렬화

coccicheck는 기본적으로 가능한 한 병렬로 실행합니다. --jobs=<number>로 동시 작업 수를 바꿀 수 있으며 CPU 4개를 사용하는 예는 다음과 같습니다.

./scripts/coccicheck --mode=report --jobs=4

Coccinelle 1.0.2부터 Ocaml parmap support가 감지되면 parmap 병렬화를 사용합니다.

Parmap이 활성화되면 coccicheck는 --chunksize 1로 dynamic load balancing을 켭니다. Thread에 작업을 하나씩 공급하므로 일부 thread만 대부분의 일을 맡는 상황을 피하고, 일찍 끝난 thread에 다음 작업을 계속 배정합니다.

Parmap 실행 중 Coccinelle error가 발생하면 그 error value가 위로 전달되고 coccicheck의 return value가 이를 반영합니다.

Semantic patch 하나만 실행

--cocci option에 적용할 semantic patch 이름을 지정하면 하나만 검사합니다.

./scripts/coccicheck --mode=report --cocci=<example.cocci>

현재 directory가 아닌 file은 path를 포함해 지정합니다.

./scripts/coccicheck --mode=report --cocci=./path/to/<example.cocci>

처리할 file 범위 제어

기본값은 source tree 전체입니다. 특정 directory만 처리하려면 command argument로 그 path를 전달합니다. 예를 들어 drivers/usb만 patch mode로 검사하려면:

./scripts/coccicheck --mode=patch drivers/usb/

report가 기본 mode이며 필요하면 앞에서 설명한 --mode=<mode>로 바꿉니다.

Coccinelle SmPL patch debug

coccicheck를 사용하면 kernel compile 때와 일치하는 include option을 spatch command line에 제공합니다. Verbose output으로 실제 option을 확인한 뒤 debug option을 추가해 Coccinelle을 직접 실행할 수 있습니다.

기본적으로 stderr는 /dev/null로 redirect됩니다. --debug=file.err를 지정하면 SmPL patch 실행의 stderr를 file로 받아 볼 수 있습니다.

rm -f cocci.err
./scripts/coccicheck --mode=patch --debug=cocci.err
cat cocci.err

추가 flag

SPFLAGS를 통해 spatch에 추가 flag를 전달합니다. Option이 충돌하면 Coccinelle이 마지막에 전달된 flag를 따르는 성질을 이용합니다.

./scripts/coccicheck --sp-flag="--use-glimpse"

idutils index

Coccinelle 1.0.6 이상은 idutils도 지원합니다. ID file을 지정하지 않으면 source tree top level의 .id-utils.index를 찾습니다. Coccinelle의 scripts/idutils_index.sh가 사용하는 방식으로 database를 만들려면:

mkid -i C --output .id-utils.index

다른 database file 이름을 사용한다면 이 이름으로 symbolic link를 만들 수 있습니다. 기본 index를 사용하려면:

./scripts/coccicheck --sp-flag="--use-idutils"

Database file을 명시적으로 지정할 수도 있습니다.

./scripts/coccicheck --sp-flag="--use-idutils /full-path/to/ID"

복잡한 macro type 제공

Definition이 부족하면 Coccinelle이 복잡한 macro variable을 인식하거나 parse하지 못할 수 있습니다. ---macro-file-builtins <headerfile.h> flag로 macro prototype을 명시하면 spatch engine이 transformation에 필요한 type 정보를 header에서 추출합니다.

Z_SYSCALL_HANDLER를 인식시키기 위해 mymacros.h에 완전한 prototype을 넣는 예:

$ cat mymacros.h
#define Z_SYSCALL_HANDLER int xxx

Transformation 때 이 header를 전달합니다.

./scripts/coccicheck --sp-flag="---macro-file-builtins mymacros.h"

spatch --help에서 더 많은 option을 확인할 수 있습니다.

SmPL patch 전용 option

SmPL patch 자체가 요구하는 Coccinelle option은 patch 맨 위에 적을 수 있습니다. 예:

// Options: --no-includes --include-headers

새 semantic patch 제안

Kernel 개발자는 새 semantic patch를 제안하고 제출할 수 있습니다. 명확한 분류를 위해 scripts/coccinelle/ 하위 directory에 배치하며 다음 성질을 갖춰야 합니다.

  • report mode를 반드시 구현합니다.
  • 첫 몇 line에서 /// comment로 script 목적을 설명합니다. 이 message는 보통 script 기반 patch의 commit log로 사용됩니다.
  • //# comment로 예외 사례나 false positive를 포함한 더 자세한 설명을 적을 수 있습니다.
  • Confidence는 false positive 수에 따라 High, Moderate, Low 중 하나로 정확도를 나타냅니다.
  • Script가 제공하는 각 mode를 virtual rule로 선언하고 그 mode를 처리하는 대응 rule을 둡니다.

목적 comment

/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element

상세 comment

//# This makes an effort to find cases where ARRAY_SIZE can be used such as
//# where there is a division of sizeof the array by the sizeof its first
//# element or by any indexed element or the element type. It replaces the
//# division of the two sizeofs by ARRAY_SIZE.

Confidence

// Confidence: High

Virtual rule

virtual context

@depends on context@
type T;
T[] E;
@@
(
* (sizeof(E)/sizeof(*E))
|
* (sizeof(E)/sizeof(E[...]))
|
* (sizeof(E)/sizeof(T))
)

이 context virtual rule은 array 전체 크기를 첫 element, 임의 indexed element 또는 element type 크기로 나누는 세 pattern을 찾습니다.

report mode 상세

report는 다음 형식의 목록을 만듭니다.

file:line:column-column: message

array_size semantic patch를 report mode로 실행하는 예:

./scripts/coccicheck --mode=report --cocci=scripts/coccinelle/array_size.cocci

이 명령은 SmPL script에서 report에 의존하는 다음 rule과 Python script를 실행합니다.

<smpl>

@r depends on (org || report)@
type T;
T[] E;
position p;
@@
(
(sizeof(E)@p /sizeof(*E))
|
(sizeof(E)@p /sizeof(E[...]))
|
(sizeof(E)@p /sizeof(T))
)

@script:python depends on report@
p << r.p;
@@

msg="WARNING: Use ARRAY_SIZE"
coccilib.report.print_report(p[0], msg)

</smpl>

position p로 찾은 위치를 Python rule에 넘기고 coccilib.report.print_report로 warning을 출력합니다. 결과 예:

ext/hal/nxp/mcux/drivers/lpc/fsl_wwdt.c:66:49-50: WARNING: Use ARRAY_SIZE
ext/hal/nxp/mcux/drivers/lpc/fsl_ctimer.c:74:53-54: WARNING: Use ARRAY_SIZE
ext/hal/nxp/mcux/drivers/imx/fsl_dcp.c:944:45-46: WARNING: Use ARRAY_SIZE

patch mode 상세

patch mode가 제공되는 semantic patch는 찾은 문제마다 수정안을 제안합니다. 실행 예:

./scripts/coccicheck --mode=patch --cocci=scripts/coccinelle/misc/array_size.cocci

Patch mode에 의존하는 SmPL rule은 세 가지 sizeof 나눗셈을 ARRAY_SIZE 호출로 바꿉니다.

<smpl>

@depends on patch@
type T;
T[] E;
@@
(
- (sizeof(E)/sizeof(*E))
+ ARRAY_SIZE(E)
|
- (sizeof(E)/sizeof(E[...]))
+ ARRAY_SIZE(E)
|
- (sizeof(E)/sizeof(T))
+ ARRAY_SIZE(E)
)

</smpl>

표준 출력에는 실제 적용 가능한 unified diff hunk가 생성됩니다.

diff -u -p a/ext/lib/encoding/tinycbor/src/cborvalidation.c b/ext/lib/encoding/tinycbor/src/cborvalidation.c
--- a/ext/lib/encoding/tinycbor/src/cborvalidation.c
+++ b/ext/lib/encoding/tinycbor/src/cborvalidation.c
@@ -325,7 +325,7 @@ static inline CborError validate_number(
static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int recursionLeft)
{
  CborType type = cbor_value_get_type(it);
-    const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
+    const size_t knownTagCount = ARRAY_SIZE(knownTagData);
   const struct KnownTagData *tagData = knownTagData;
   const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount;

context mode 상세

context는 관심 line과 주변 문맥을 diff와 비슷한 형태로 표시합니다.

실행 예:

./scripts/coccicheck --mode=context --cocci=scripts/coccinelle/array_size.cocci

Context에 의존하는 SmPL rule:

<smpl>

@depends on context@
type T;
T[] E;
@@
(
* (sizeof(E)/sizeof(*E))
|
* (sizeof(E)/sizeof(E[...]))
|
* (sizeof(E)/sizeof(T))
)

</smpl>

표준 출력의 diff 형태 예:

diff -u -p ext/lib/encoding/tinycbor/src/cborvalidation.c /tmp/nothing/ext/lib/encoding/tinycbor/src/cborvalidation.c
--- ext/lib/encoding/tinycbor/src/cborvalidation.c
+++ /tmp/nothing/ext/lib/encoding/tinycbor/src/cborvalidation.c
@@ -325,7 +325,6 @@ static inline CborError validate_number(
static inline CborError validate_tag(CborValue *it, CborTag tag, int flags, int recursionLeft)
{
  CborType type = cbor_value_get_type(it);
-    const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]);
   const struct KnownTagData *tagData = knownTagData;
   const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount;

org mode 상세

org는 Emacs Org mode 형식의 report를 만듭니다. 실행 예:

./scripts/coccicheck --mode=org --cocci=scripts/coccinelle/misc/array_size.cocci

Report와 같은 match 위치를 사용하지만 Python rule은 Org todo entry를 출력합니다.

<smpl>

@r depends on (org || report)@
type T;
T[] E;
position p;
@@
(
(sizeof(E)@p /sizeof(*E))
|
(sizeof(E)@p /sizeof(E[...]))
|
(sizeof(E)@p /sizeof(T))
)

@script:python depends on org@
p << r.p;
@@
coccilib.org.print_todo(p[0], "WARNING should use ARRAY_SIZE")

</smpl>

표준 출력의 Org entry 예:

* TODO [[view:ext/lib/encoding/tinycbor/src/cborvalidation.c::face=ovl-face1::linb=328::colb=52::cole=53][WARNING should use ARRAY_SIZE]]

Coccinelle mailing list

Cocci mailing list 구독 페이지에서 가입할 수 있습니다.

Archive는 lore.kernel.org/cocci와 systeme.lip6.fr archive에서 볼 수 있습니다.

Source

출처

영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.