Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scripts: coccinelle #3991

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

AndreaTagliavini
Copy link

scripts: add Coccinelle support

Having to deal with a large project, it is useful to have a tool that allows developers to analyze their code.
Coccinelle is a software used to match code patterns and to transform them programmatically, using ".cocci"scripts, which are also called: Semantic Patches.
This pull request, implements "coccicheck", a script that allows to run semantic patches on the OP-TEE code in three possible ways:

  • Run a local semantic patch
  • Run a whole set of local semantic patches
  • Run a set of external semantic patches
    The script is callable as a makefile target, so in order to launch it run:
    make coccicheck

The pull request also adds three semantic patches:

  • bad_null: produces patches which simplify expressions that compare to NULL
  • initialize_variables: matches non-initialized variables and produces patches that do so
  • warning_overflow: prints a warning on each occurrence of a specific pattern that could cause an overflow
    All the patches produced by this tool are printed to stdout.

Coccinelle is a utility tool used to match specific code patterns in
order to modify or statically analyze them.
".cocci"scripts (Semantic Patches) are used to define such patterns and
also to specify what actions have to be performed.
Add script coccicheck, which allows to execute Coccinelle semantic
patches on top of op-tee source code.
It is called using the "coccicheck" target in the op-tee Makefile.
The script invokes semantic patches in 3 fashions:
	- use a single semantic patch: specify and execute a single
	  semantic patch from the local set.
	- use multiple semantic patches: execute all semantic patches
	  from the local set.
	- use a subset of external patches: specify a single or
	  multiple semantic patches, defined outside of the local set.

Reviewed-by: Paolo Valente <[email protected]>
Signed-off-by: Andrea Tagliavini <[email protected]>
Add a semantic patch that matches various boolean expressions that
compare to NULL, and produces patches that replace them with an
equivalent reduced form (e.g. "foo == NULL" becomes "!foo").

Reviewed-by: Paolo Valente <[email protected]>
Signed-off-by: Andrea Tagliavini <[email protected]>
Add a semantic patch that matches non-initialized variables and produces
patches that set values depending on the variable type.
  - Numeric variables are set to 0
  - Size_t arrays are set to {0}
  - Other arrays are set to {NULL}
  - Every other variable is set to NULL

Reviewed-by: Paolo Valente <[email protected]>
Signed-off-by: Andrea Tagliavini <[email protected]>
Add a semantic patch that matches the following construct:
  if(A + B > C)
For each occurrence of the construct, a warning is printed, in order to
highlight possible overflows.

Reviewed-by: Paolo Valente <[email protected]>
Signed-off-by: Andrea Tagliavini <[email protected]>
@AndreaTagliavini AndreaTagliavini changed the title Coccinelle dev scripts: coccinelle Jul 22, 2020
@jenswi-linaro
Copy link
Contributor

Nice work! Can you add SPDX-License-Identifier for all the files too please?

@jenswi-linaro
Copy link
Contributor

Is it possible to use this on individual diffs/patches too or do you need to run it on the entire tree?
It would be nice to be able to test only the diff of a pull request. A bit like what we can do with checkpatch.

@jenswi-linaro
Copy link
Contributor

jenswi-linaro commented Jul 22, 2020

It would also be nice to ignore certain directories and files, like what we're ignoring for checkpatch:

                core/include/gen-asm-defines.h \
                core/lib/lib{fdt,tomcrypt} core/lib/zlib \
                lib/libutils lib/libmbedtls \
                core/arch/arm/include/arm{32,64}.h \
                core/arch/arm/plat-ti/api_monitor_index_a{9,15}.h \
                core/arch/arm/dts

@jforissier
Copy link
Contributor

Regarding variable initialization: we initalize structs and arrays with = { };.

Add SPDX-License-Identifier.
Add option USE_SUBTREE, which let one run semantic patches on a
specific directory instead of the whole tree.

Signed-off-by: Andrea Tagliavini <[email protected]>
Add SPDX-License-Identifier to semantic patches.

Signed-off-by: Andrea Tagliavini <[email protected]>
@AndreaTagliavini
Copy link
Author

Nice work! Can you add SPDX-License-Identifier for all the files too please?

I added just the identifier, if you want i could also add the copyright

@AndreaTagliavini
Copy link
Author

Is it possible to use this on individual diffs/patches too or do you need to run it on the entire tree?
It would be nice to be able to test only the diff of a pull request. A bit like what we can do with checkpatch.

I just added an option that allows one to specify a sub-tree, so semantic patches are executed just from that location (but still recursively).

@jenswi-linaro
Copy link
Contributor

Nice work! Can you add SPDX-License-Identifier for all the files too please?

I added just the identifier, if you want i could also add the copyright

Yes please.

@jenswi-linaro
Copy link
Contributor

Is it possible to use this on individual diffs/patches too or do you need to run it on the entire tree?
It would be nice to be able to test only the diff of a pull request. A bit like what we can do with checkpatch.

I just added an option that allows one to specify a sub-tree, so semantic patches are executed just from that location (but still recursively).

If we could have another option to skip a number of sub-trees also it would be perfect. The problem is that we have certain 3rd-party libraries like LTC and mbedTLS that we'd rather not get warnings from unless we choose to.

checkpatch: checkpatch-staging checkpatch-working

checkpatch-working:
${q}./scripts/checkpatch.sh

checkpatch-staging:
${q}./scripts/checkpatch.sh --cached

coccicheck:
${q} ./scripts/coccicheck
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: remove space, for consistency with the makefile.

@@ -0,0 +1,132 @@
#!/bin/bash

DIR="`pwd`"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DIR not used. can remove.


SPATCH="`which ${SPATCH:=spatch}`"
if [ ! -x "$SPATCH" ]; then
echo 'spatch is required to run this script, exiting.'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest "Error: " as prefix trace message.

###########################################################################################
# Help section

if [[ $H -ge 1 ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is $H?

# Help section

if [[ $H -ge 1 ]]; then
echo "coccicheck help section"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe: "Help section for optee_os makefile coccicheck target"
Looks strange that this shell script shows debug info related to makefile usage.


/************************************************************************************
* This semantic patch matches all occurrencies of variable declaration without
* initialization and then initializes them accordingly to their type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/accordingly/according/

|
// size_t array
size_t v[]
+ = {0}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer { 0 } over {0}.

|
// every other type
t v
+ = NULL
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really applicable? NULL likely not applies to structure, enums, ...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just thinking of a placeholder value to assign to every other type, but you're right. Maybe for now i can simply remove these lines, and let others specify a type when necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer = { } for anonymous type as per Optee OS coding rules.

|
// generic array
t v[]
+ = {NULL}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


coccinelle () {
COCCI="$1"
run_cmd $SPATCH $VIRTUAL $FLAGS --cocci-file $COCCI $OPTIONS || exit 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FLAGS used here is not documented. It is related to coccinelle legacy env variables?

@github-actions
Copy link

This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants