diff options
Diffstat (limited to 'scripts/coccinelle')
-rwxr-xr-x | scripts/coccinelle/apply.sh | 9 | ||||
-rwxr-xr-x | scripts/coccinelle/check_cocci_parse.sh | 53 | ||||
-rw-r--r-- | scripts/coccinelle/exceptions.txt | 24 | ||||
-rwxr-xr-x | scripts/coccinelle/test-operator-cleanup | 13 | ||||
-rw-r--r-- | scripts/coccinelle/tor-coccinelle.h | 60 | ||||
-rwxr-xr-x | scripts/coccinelle/try_parse.sh | 46 |
6 files changed, 205 insertions, 0 deletions
diff --git a/scripts/coccinelle/apply.sh b/scripts/coccinelle/apply.sh new file mode 100755 index 0000000000..f531d7fa32 --- /dev/null +++ b/scripts/coccinelle/apply.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# apply.sh: +# run spatch with appropriate includes and builtins for the Tor source code + +top="$(dirname "$0")/../.." + +spatch -macro_file_builtins "$top"/scripts/coccinelle/tor-coccinelle.h \ + -I "$top" -I "$top"/src -I "$top"/ext --defined COCCI "$@" diff --git a/scripts/coccinelle/check_cocci_parse.sh b/scripts/coccinelle/check_cocci_parse.sh new file mode 100755 index 0000000000..220b405940 --- /dev/null +++ b/scripts/coccinelle/check_cocci_parse.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +# If we have coccinelle installed, run try_parse.sh on every filename passed +# as an argument. If no filenames are supplied, scan a standard Tor 0.3.5 or +# later directory layout. +# +# Uses the default coccinelle exceptions file, or $TOR_COCCI_EXCEPTIONS_FILE, +# if it is set. +# +# Use TOR_COCCI_EXCEPTIONS_FILE=/dev/null check_cocci_parse.sh to disable +# the default exception file. +# +# If spatch is not installed, remind the user to install it, but exit with +# a success error status. + +scripts_cocci="$(dirname "$0")" +top="$scripts_cocci/../.." +try_parse="$scripts_cocci/try_parse.sh" + +exitcode=0 + +export TOR_COCCI_EXCEPTIONS_FILE="${TOR_COCCI_EXCEPTIONS_FILE:-$scripts_cocci/exceptions.txt}" + +if ! command -v spatch; then + echo "Install coccinelle's spatch to check cocci C parsing!" + exit "$exitcode" +fi + +if test $# -ge 1 ; then + "$try_parse" "$@" + exitcode=$? +else + cd "$top" || exit 1 + # This is the layout in 0.3.5 + "$try_parse" \ + src/lib/*/*.[ch] \ + src/core/*/*.[ch] \ + src/feature/*/*.[ch] \ + src/app/*/*.[ch] \ + src/test/*.[ch] \ + src/test/*/*.[ch] \ + src/tools/*.[ch] + exitcode=$? +fi + +if test "$exitcode" != 0 ; then + echo "Please fix these cocci parsing errors in the above files" + echo "Set VERBOSE=1 for more details" + echo "Try running test-operator-cleanup or 'make autostyle-operators'" + echo "As a last resort, you can modify scripts/coccinelle/exceptions.txt" +fi + +exit "$exitcode" diff --git a/scripts/coccinelle/exceptions.txt b/scripts/coccinelle/exceptions.txt new file mode 100644 index 0000000000..473f4b22c5 --- /dev/null +++ b/scripts/coccinelle/exceptions.txt @@ -0,0 +1,24 @@ +# A list of exception patterns for check_cocci_parse.sh +# Passed to 'grep -f' +src/lib/cc/compat_compiler.h +src/lib/container/handles.h +src/lib/container/map.c +src/lib/container/map.h +src/lib/container/order.c +src/lib/crypt_ops/crypto_rand.c +src/lib/fs/files.h +src/lib/log/util_bug.c +src/lib/pubsub/pubsub_macros.h +src/lib/smartlist_core/smartlist_foreach.h +src/lib/testsupport/testsupport.h +src/lib/tls/tortls.h +src/lib/tls/tortls_openssl.c +src/lib/tls/x509.h +src/lib/version/version.c +src/core/mainloop/connection.c +src/core/or/reasons.c +src/feature/dirclient/dirclient.c +src/feature/nodelist/networkstatus.c +src/test/test_address.c +src/test/test_hs_cache.c +src/test/test_hs_descriptor.c diff --git a/scripts/coccinelle/test-operator-cleanup b/scripts/coccinelle/test-operator-cleanup index e7822542a4..28b4d4f588 100755 --- a/scripts/coccinelle/test-operator-cleanup +++ b/scripts/coccinelle/test-operator-cleanup @@ -1,4 +1,17 @@ #!/usr/bin/perl -w -p -i +# +# Copyright (c) 2001 Matej Pfajfar. +# Copyright (c) 2001-2004, Roger Dingledine. +# Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. +# Copyright (c) 2007-2019, The Tor Project, Inc. +# See LICENSE for licensing information + +# This script looks for instances of C comparison operators as macro arguments, +# and replaces them with our OP_* equivalents. +# +# Some macros that take operators are our tt_int_op() testing macro, and the +# standard timercmp() macro. Coccinelle can't handle their syntax, however, +# unless we give them their operators as a macro too. next if m#^ */\*# or m#^ *\* #; diff --git a/scripts/coccinelle/tor-coccinelle.h b/scripts/coccinelle/tor-coccinelle.h index 8f625dcee4..44d79325eb 100644 --- a/scripts/coccinelle/tor-coccinelle.h +++ b/scripts/coccinelle/tor-coccinelle.h @@ -1,3 +1,63 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/* + * This file looks like a C header, but its purpose is a bit different. + * + * We never include it from our real C files; we only tell Coccinelle + * about it in apply.sh. + * + * It tells the Coccinelle semantic patching tool how to understand + * things that would otherwise not be good C syntax, or which would + * otherwise not make sense to it as C. It doesn't need to produce + * semantically equivalent C, or even correct C: it only has to produce + * syntactically valid C. + */ + +#define MOCK_DECL(a, b, c) a b c #define MOCK_IMPL(a, b, c) a b c #define CHECK_PRINTF(a, b) +#define CHECK_SCANF(a, b) #define STATIC static +#define EXTERN(a,b) extern a b; + +#define STMT_BEGIN do { +#define STMT_END } while (0) + +#define BUG(x) (x) +#define IF_BUG_ONCE(x) if (x) + +#define ATTR_NORETURN +#define ATTR_UNUSED +#define ATTR_CONST +#define ATTR_MALLOC +#define ATTR_WUR +#define DISABLE_GCC_WARNING(x) +#define ENABLE_GCC_WARNING(x) + +#define HANDLE_DECL(a,b,c) +#define HANDLE_IMPL(a,b,c) +#define HT_ENTRY(x) void * +#define HT_HEAD(a,b) struct ht_head +#define HT_INITIALIZER() { } +#define X509 struct x509_st +#define STACK_OF(x) struct foo_stack_t +#define TOR_TAILQ_HEAD(a,b) struct tailq_head +#define TOR_TAILQ_ENTRY(a) struct tailq_entry +#define TOR_SIMPLEQ_HEAD(a,b) struct simpleq_entry +#define TOR_SIMPLEQ_ENTRY(a) struct simpleq_entry +#define TOR_LIST_HEAD(a,b) struct list_head +#define TOR_LIST_ENTRY(a) struct list_entry +#define TOR_SLIST_HEAD(a,b) struct slist_head +#define TOR_SLIST_ENTRY(a) struct slist_entry + +#define NS_DECL(a, b, c) a b c +#define NS(a) a + +#define CONF_TEST_MEMBERS(a,b,c) +#define DUMMY_CONF_TEST_MEMBERS + +#define EAT_SEMICOLON extern int dummy__; diff --git a/scripts/coccinelle/try_parse.sh b/scripts/coccinelle/try_parse.sh new file mode 100755 index 0000000000..a90e51b4aa --- /dev/null +++ b/scripts/coccinelle/try_parse.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +# Echo the name of every argument of this script that is not "perfect" +# according to coccinelle's --parse-c. +# +# If $TOR_COCCI_EXCEPTIONS_FILE is non-empty, skip any files that match the +# patterns in the exception file, according to "grep -f" +# +# If VERBOSE is non-empty, log spatch errors and skipped files. + +top="$(dirname "$0")/../.." + +exitcode=0 + +for fn in "$@"; do + + if test "${TOR_COCCI_EXCEPTIONS_FILE}" ; then + skip_fn=$(echo "$fn" | grep -f "${TOR_COCCI_EXCEPTIONS_FILE}") + if test "${skip_fn}" ; then + if test "${VERBOSE}" != ""; then + echo "Skipping '${skip_fn}'" + fi + continue + fi + fi + + if spatch --macro-file-builtins \ + "$top"/scripts/coccinelle/tor-coccinelle.h \ + --defined COCCI \ + --parse-c "$fn" \ + 2>/dev/null | grep "perfect = 1" > /dev/null; then + : # it's perfect + else + echo "$fn" + if test "${VERBOSE}" != ""; then + spatch --macro-file-builtins \ + "$top"/scripts/coccinelle/tor-coccinelle.h \ + --defined COCCI \ + --parse-c "$fn" + fi + exitcode=1 + fi + +done + +exit "$exitcode" |