forked from sysprog21/lab0-c
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pre-commit.hook
executable file
·144 lines (128 loc) · 4.16 KB
/
pre-commit.hook
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env bash
CPPCHECK_unmatched=
for f in *.c; do
CPPCHECK_unmatched="$CPPCHECK_unmatched --suppress=unmatchedSuppression:$f"
done
CPPCHECK_suppresses="--inline-suppr harness.c \
--suppress=missingIncludeSystem \
--suppress=noValidConfiguration \
--suppress=unusedFunction \
--suppress=identicalInnerCondition:log2_lshift16.h \
--suppress=nullPointerRedundantCheck:report.c \
--suppress=nullPointerRedundantCheck:harness.c \
--suppress=nullPointer:queue.c \
--suppress=nullPointer:qtest.c"
CPPCHECK_OPTS="-I. --enable=all --error-exitcode=1 --force $CPPCHECK_suppresses $CPPCHECK_unmatched ."
RETURN=0
CLANG_FORMAT=$(which clang-format)
if [ $? -ne 0 ]; then
echo "[!] clang-format not installed. Unable to check source file format policy." >&2
exit 1
fi
CPPCHECK=$(which cppcheck)
if [ $? -ne 0 ]; then
echo "[!] cppcheck not installed. Unable to perform static analysis." >&2
exit 1
fi
# Expected Cppcheck version is 1.90+
# First, Cppcheck 2.x
if [ -z "$($CPPCHECK --version | grep -E '^Cppcheck\s2')" ]; then
# Second, Cppcheck 1.x
CPPCHECK_VER=$($CPPCHECK --version | sed -Ee 's/Cppcheck 1.([0-9]+)/\1/;q')
if [ $CPPCHECK_VER -lt 90 ]; then
echo "[!] cppcheck version must be at least 1.90." >&2
echo -e " Check 'Developer Info' for building Cppcheck from source:\n" \
" https://cppcheck.sourceforge.net/devinfo/" >&2
exit 1
fi
fi
ASPELL=$(which aspell)
if [ $? -ne 0 ]; then
echo "[!] aspell not installed. Unable to do spelling check." >&2
exit 1
fi
if [ -z "$(aspell dump dicts | grep -E '^en$')" ]; then
echo "[!] aspell-en not installed. Unable to do spelling check." >&2
exit 1
fi
DIFF=$(which colordiff)
if [ $? -ne 0 ]; then
DIFF=diff
fi
SHA1SUM=$(which sha1sum)
if [ $? -ne 0 ]; then
SHA1SUM=shasum
fi
FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E "\.(c|cpp|h)$")
for FILE in $FILES; do
nf=$(git checkout-index --temp $FILE | cut -f 1)
tempdir=$(mktemp -d) || exit 1
newfile=$(mktemp ${tempdir}/${nf}.XXXXXX) || exit 1
basename=$(basename $FILE)
source="${tempdir}/${basename}"
mv $nf $source
cp .clang-format $tempdir
$CLANG_FORMAT $source > $newfile 2>> /dev/null
$DIFF -u -p -B --label="modified $FILE" --label="expected coding style" \
"${source}" "${newfile}"
r=$?
rm -rf "${tempdir}"
if [ $r != 0 ] ; then
echo "[!] $FILE does not follow the consistent coding style." >&2
RETURN=1
fi
if [ $RETURN -eq 1 ]; then
echo "" >&2
echo "Make sure you indent as the following:" >&2
echo " clang-format -i $FILE" >&2
echo
fi
done
if [ ! -z "${FILES[*]}" ]; then
echo "Following files need to be cleaned up:"
echo "${FILES[*]}"
fi
$SHA1SUM -c scripts/checksums >/dev/null
if [ $? -ne 0 ]; then
echo "[!] You are not allowed to change the header file queue.h or list.h" >&2
exit 1
fi
# Prevent unsafe functions
root=$(git rev-parse --show-toplevel)
banned="([^f]gets\()|(sprintf\()|(strcpy\()"
status=0
for file in $(git diff --staged --name-only | grep -E "\.(c|cc|cpp|h|hh|hpp)\$")
do
filepath="${root}/${file}"
output=$(grep -nrE "${banned}" "${filepath}")
if [ ! -z "${output}" ]; then
echo "Dangerous function detected in ${filepath}"
echo "${output}"
echo
echo "Read 'Common vulnerabilities guide for C programmers' carefully."
echo " https://security.web.cern.ch/security/recommendations/en/codetools/c.shtml"
RETURN=1
fi
done
# static analysis
$CPPCHECK $CPPCHECK_OPTS >/dev/null
if [ $? -ne 0 ]; then
RETURN=1
echo "" >&2
echo "Fail to pass static analysis." >&2
echo
fi
# non-ASCII filenames are not allowed.
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository.
if test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
ERROR: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
EOF
RETURN=1
fi
exit $RETURN