1#!/bin/bash
2# Note: tested with cppcheck 1.72 as shipped with Ubuntu 16.04
3# as well as with cppcheck 1.76.1
4
5set -eu
6
7SCRIPT_DIR=$(dirname "$0")
8case $SCRIPT_DIR in
9    "/"*)
10        ;;
11    ".")
12        SCRIPT_DIR=$(pwd)
13        ;;
14    *)
15        SCRIPT_DIR=$(pwd)/$(dirname "$0")
16        ;;
17esac
18GDAL_ROOT=$SCRIPT_DIR/..
19cd "$GDAL_ROOT"
20
21
22LOG_FILE=/tmp/cppcheck_gdal.txt
23
24CPPCHECK_VERSION="$(cppcheck --version | awk '{print $2}')"
25if test $(expr $CPPCHECK_VERSION \>= 1.84) = 1; then
26    OVERRIDE=
27else
28    OVERRIDE="-Doverride="
29fi
30
31echo "" > ${LOG_FILE}
32for dirname in alg port gcore ogr frmts gnm apps fuzzers; do
33    printf "Running cppcheck on %s (can be long): " "$dirname"
34    cppcheck --inline-suppr --template='{file}:{line},{severity},{id},{message}' \
35        --enable=all --inconclusive --std=posix -UAFL_FRIENDLY -UANDROID \
36        -UCOMPAT_WITH_ICC_CONVERSION_CHECK -DDEBUG -UDEBUG_BOOL -DHAVE_CXX11=1 \
37        -D__linux \
38        -DGBool=int -DCPL_HAS_GINT64=1 -DHAVE_GEOS -DHAVE_EXPAT -DHAVE_XERCES -DCOMPILATION_ALLOWED \
39        -DHAVE_SFCGAL -DHAVE_SPATIALITE -DSPATIALITE_412_OR_LATER \
40        -DHAVE_SQLITE -DSQLITE_VERSION_NUMBER=3006000 -DHAVE_SQLITE_VFS \
41        -DHAVE_RASTERLITE2 \
42        -DHAVE_CURL -DLIBCURL_VERSION_NUM=0x073800 \
43        -DPTHREAD_MUTEX_RECURSIVE -DCPU_LITTLE_ENDIAN -DCPL_IS_LSB=1 \
44        -DKDU_MAJOR_VERSION=7 -DKDU_MINOR_VERSION=5 \
45        -DHAVE_JASPER_UUID \
46        -D__GNUC__==5 -DGDAL_COMPILATION \
47        -DODBCVER=0x0300 \
48        -DNETCDF_HAS_NC4 \
49        -DJPEG_SUPPORTED \
50        -DJPEG_DUAL_MODE_8_12 \
51        -D_TOOLKIT_IN_DLL_ \
52        -UGDAL_NO_AUTOLOAD \
53        -DHAVE_MITAB \
54        -Dva_copy=va_start \
55        -D__cplusplus=201103 \
56        -DVSIRealloc=realloc \
57        -DCPPCHECK \
58        -DDEBUG_MUTEX \
59        -DDEBUG_PROXY_POOL \
60        ${OVERRIDE} \
61        -DOCAD_EXTERN= \
62        -DTIFFLIB_VERSION=99999999 \
63        -DHAVE_SSE_AT_COMPILE_TIME \
64        -DHAVE_LIBXML2 \
65        -DCPL_INTERNAL= \
66        -DCHAR_BIT=8 \
67        -DUCHAR_MAX=255 \
68        -DSHRT_MIN=-32768 \
69        -DSHRT_MAX=32767 \
70        -DUSHRT_MAX=65535 \
71        -DINT_MIN=-2147483648 \
72        -DINT_MAX=2147483647 \
73        -DUINT_MAX=4294967295U \
74        --include=port/cpl_config.h \
75        --include=port/cpl_port.h \
76        -I port -I gcore -I ogr -I ogr/ogrsf_frmts -I ogr/ogrsf_frmts/geojson \
77        -I ogr/ogrsf_frmts/geojson/libjson \
78        -i cpl_mem_cache.h \
79        -i ogrdissolve.cpp \
80        -i gdalasyncread.cpp \
81        -i gdaltorture.cpp \
82        $dirname \
83        -j "$(nproc)" >>${LOG_FILE} 2>&1 &
84    # Display some progress to avoid Travis-CI killing the job after 10 minutes
85    PID=$!
86    while kill -0 $PID 2>/dev/null; do
87        printf "."
88        sleep 1
89    done
90    echo " done"
91    if ! wait $PID; then
92        echo "cppcheck failed"
93        exit 1
94    fi
95done
96
97ret_code=0
98
99grep -v "unmatchedSuppression" ${LOG_FILE} | grep -v -e " yacc.c" -e PublicDecompWT -e "kdu_cache_wrapper.h" > ${LOG_FILE}.tmp
100mv ${LOG_FILE}.tmp ${LOG_FILE}
101
102# I don't want to care about SDE
103grep -v -e "frmts/sde" -e  "ogr/ogrsf_frmts/sde" ${LOG_FILE} > ${LOG_FILE}.tmp
104mv ${LOG_FILE}.tmp ${LOG_FILE}
105
106# I don't want to care about flatbuffers
107grep -v -e "ogr/ogrsf_frmts/flatgeobuf/flatbuffers" ${LOG_FILE} > ${LOG_FILE}.tmp
108mv ${LOG_FILE}.tmp ${LOG_FILE}
109
110# False positive deallocuse
111grep -v -e "frmts/png/libpng/png.c" ${LOG_FILE} > ${LOG_FILE}.tmp
112mv ${LOG_FILE}.tmp ${LOG_FILE}
113
114if grep "null pointer" ${LOG_FILE} ; then
115    echo "Null pointer check failed"
116    ret_code=1
117fi
118
119if grep "duplicateBreak" ${LOG_FILE} ; then
120    echo "duplicateBreak check failed"
121    ret_code=1
122fi
123
124if grep "duplicateBranch" ${LOG_FILE} ; then
125    echo "duplicateBranch check failed"
126    ret_code=1
127fi
128
129if grep "uninitMemberVar" ${LOG_FILE} ; then
130    echo "uninitMemberVar check failed"
131    ret_code=1
132fi
133
134if grep "useInitializationList" ${LOG_FILE} ; then
135    echo "uninitMemberVar check failed"
136    ret_code=1
137fi
138
139if grep "clarifyCalculation" ${LOG_FILE} ; then
140    echo "clarifyCalculation check failed"
141    ret_code=1
142fi
143
144if grep "invalidPrintfArgType_uint" ${LOG_FILE} ; then
145    echo "invalidPrintfArgType_uint check failed"
146    ret_code=1
147fi
148
149if grep "catchExceptionByValue" ${LOG_FILE} ; then
150    echo "catchExceptionByValue check failed"
151    ret_code=1
152fi
153
154grep "memleakOnRealloc" ${LOG_FILE} | grep frmts/hdf4/hdf-eos > /dev/null && echo "memleakOnRealloc issues in frmts/hdf4/hdf-eos ignored"
155grep "memleakOnRealloc" ${LOG_FILE} | grep frmts/grib/degrib > /dev/null && echo "memleakOnRealloc issues in frmts/grib/degrib ignored"
156
157if grep "memleakOnRealloc" ${LOG_FILE} | grep -v -e frmts/hdf4/hdf-eos -e frmts/grib/degrib ; then
158    echo "memleakOnRealloc check failed"
159    ret_code=1
160fi
161
162# Those warnings in libjpeg seems to be false positives
163#grep "arrayIndexOutOfBoundsCond" ${LOG_FILE} | grep frmts/jpeg/libjpeg > /dev/null && echo "arrayIndexOutOfBoundsCond issues in frmts/jpeg/libjpeg ignored"
164if grep "arrayIndexOutOfBoundsCond" ${LOG_FILE} | grep -v frmts/jpeg/libjpeg ; then
165    echo "arrayIndexOutOfBoundsCond check failed"
166    ret_code=1
167fi
168
169grep "arrayIndexOutOfBounds," ${LOG_FILE} | grep frmts/hdf4/hdf-eos > /dev/null && echo "arrayIndexOutOfBounds issues in frmts/hdf4/hdf-eos ignored"
170if grep "arrayIndexOutOfBounds," ${LOG_FILE} | grep -v frmts/hdf4/hdf-eos ; then
171    echo "arrayIndexOutOfBounds check failed"
172    ret_code=1
173fi
174
175if grep "syntaxError" ${LOG_FILE} | grep -v "is invalid C code" ; then
176    echo "syntaxError check failed"
177    ret_code=1
178fi
179
180grep "memleak," ${LOG_FILE} | grep frmts/hdf4/hdf-eos > /dev/null && echo "memleak issues in frmts/hdf4/hdf-eos ignored"
181grep "memleak," ${LOG_FILE} | grep frmts/grib/degrib > /dev/null && echo "memleak issues in frmts/grib/degrib ignored"
182if grep "memleak," ${LOG_FILE} | grep -v -e frmts/hdf4/hdf-eos -e frmts/grib/degrib ; then
183    echo "memleak check failed"
184    ret_code=1
185fi
186
187if grep "eraseDereference" ${LOG_FILE} ; then
188    echo "eraseDereference check failed"
189    ret_code=1
190fi
191
192if grep "memsetClass," ${LOG_FILE} ; then
193    echo "memsetClass check failed"
194    ret_code=1
195fi
196
197# Most if not all of them are false positives
198grep "uninitvar," ${LOG_FILE} | grep frmts/hdf4/hdf-eos > /dev/null && echo "(potential) uninitvar issues in frmts/hdf4/hdf-eos ignored"
199grep "uninitvar," ${LOG_FILE} | grep frmts/grib/degrib > /dev/null && echo "(potential) uninitvar issues in frmts/grib/degrib ignored"
200grep "uninitvar," ${LOG_FILE} | grep frmts/gtiff/libtiff > /dev/null && echo "(potential) uninitvar issues in frmts/gtiff/libtiff ignored"
201grep "uninitvar," ${LOG_FILE} | grep frmts/gtiff/libgeotiff > /dev/null && echo "(potential) uninitvar issues in frmts/gtiff/libgeotiff ignored"
202grep "uninitvar," ${LOG_FILE} | grep frmts/jpeg/libjpeg > /dev/null && echo "(potential) uninitvar issues in frmts/jpeg/libjpeg ignored"
203grep "uninitvar," ${LOG_FILE} | grep frmts/gif/giflib > /dev/null && echo "(potential) uninitvar issues in frmts/gif/giflib ignored"
204grep "uninitvar," ${LOG_FILE} | grep frmts/png/libpng > /dev/null && echo "(potential) uninitvar issues in frmts/png/libpng ignored"
205grep "uninitvar," ${LOG_FILE} | grep frmts/zlib > /dev/null && echo "(potential) uninitvar issues in frmts/zlib ignored"
206grep "uninitvar," ${LOG_FILE} | grep ogr/ogrsf_frmts/geojson/libjson > /dev/null && echo "(potential) uninitvar issues in ogr/ogrsf_frmts/geojson/libjson ignored"
207
208if grep "uninitvar," ${LOG_FILE} | grep -v -e frmts/hdf4/hdf-eos \
209        -e frmts/grib/degrib -e frmts/gtiff/libtiff -e frmts/gtiff/libgeotiff \
210        -e frmts/jpeg/libjpeg -e frmts/gif/giflib -e frmts/png/libpng \
211        -e frmts/zlib -e ogr/ogrsf_frmts/geojson/libjson \
212        -e osr_cs_wkt_parser.c ; then
213    echo "uninitvar check failed"
214    ret_code=1
215fi
216
217grep "uninitdata," ${LOG_FILE} | grep "frmts/grib/degrib/g2clib" > /dev/null && echo "(potential) uninitdata issues in frmts/grib/degrib/g2clib ignored"
218
219if grep "uninitdata," ${LOG_FILE} | grep -v "frmts/grib/degrib/g2clib" ; then
220    echo "uninitdata check failed"
221    ret_code=1
222fi
223
224if grep "va_list_usedBeforeStarted" ${LOG_FILE} ; then
225    echo "va_list_usedBeforeStarted check failed"
226    ret_code=1
227fi
228
229if grep "duplInheritedMember" ${LOG_FILE} ; then
230    echo "duplInheritedMember check failed"
231    ret_code=1
232fi
233
234if grep "terminateStrncpy" ${LOG_FILE} ; then
235    echo "terminateStrncpy check failed"
236    ret_code=1
237fi
238
239if grep "operatorEqVarError" ${LOG_FILE} ; then
240    echo "operatorEqVarError check failed"
241    ret_code=1
242fi
243
244if grep "uselessAssignmentPtrArg" ${LOG_FILE} | grep -v -e swq_parser.cpp -e osr_cs_wkt_parser.c -e ods_formula_parser.cpp ; then
245    echo "uselessAssignmentPtrArg check failed"
246    ret_code=1
247fi
248
249if grep "bufferNotZeroTerminated" ${LOG_FILE} ; then
250    echo "bufferNotZeroTerminated check failed"
251    ret_code=1
252fi
253
254if grep "sizeofDivisionMemfunc" ${LOG_FILE} ; then
255    echo "sizeofDivisionMemfunc check failed"
256    ret_code=1
257fi
258
259if grep "selfAssignment" ${LOG_FILE} ; then
260    echo "selfAssignment check failed"
261    ret_code=1
262fi
263
264if grep "invalidPrintfArgType_sint" ${LOG_FILE} ; then
265    echo "invalidPrintfArgType_sint check failed"
266    ret_code=1
267fi
268
269if grep "redundantAssignInSwitch" ${LOG_FILE} ; then
270    echo "redundantAssignInSwitch check failed"
271    ret_code=1
272fi
273
274if grep "publicAllocationError" ${LOG_FILE} ; then
275    echo "publicAllocationError check failed"
276    ret_code=1
277fi
278
279if grep "invalidScanfArgType_int" ${LOG_FILE} ; then
280    echo "invalidScanfArgType_int check failed"
281    ret_code=1
282fi
283
284if grep "invalidscanf," ${LOG_FILE} ; then
285    echo "invalidscanf check failed"
286    ret_code=1
287fi
288
289if grep "moduloAlwaysTrueFalse" ${LOG_FILE} ; then
290    echo "moduloAlwaysTrueFalse check failed"
291    ret_code=1
292fi
293
294if grep "charLiteralWithCharPtrCompare" ${LOG_FILE} ; then
295    echo "charLiteralWithCharPtrCompare check failed"
296    ret_code=1
297fi
298
299if grep "noConstructor" ${LOG_FILE} ; then
300    echo "noConstructor check failed"
301    ret_code=1
302fi
303
304if grep "noExplicitConstructor" ${LOG_FILE} ; then
305    echo "noExplicitConstructor check failed"
306    ret_code=1
307fi
308
309if grep "noCopyConstructor" ${LOG_FILE} ; then
310    echo "noCopyConstructor check failed"
311    ret_code=1
312fi
313
314if grep "passedByValue" ${LOG_FILE} ; then
315    echo "passedByValue check failed"
316    ret_code=1
317fi
318
319if grep "postfixOperator" ${LOG_FILE} ; then
320    echo "postfixOperator check failed"
321    ret_code=1
322fi
323
324if grep "redundantCopy" ${LOG_FILE} ; then
325    echo "redundantCopy check failed"
326    ret_code=1
327fi
328
329if grep "stlIfStrFind" ${LOG_FILE} ; then
330    echo "stlIfStrFind check failed"
331    ret_code=1
332fi
333
334if grep "functionStatic" ${LOG_FILE} | grep -v -e OGRSQLiteDataSource::OpenRaster \
335                                            -e OGRSQLiteDataSource::OpenRasterSubDataset \
336                                            -e cpl_mem_cache ; then
337    echo "functionStatic check failed"
338    ret_code=1
339fi
340
341if grep "knownConditionTrueFalse" ${LOG_FILE} ; then
342    echo "knownConditionTrueFalse check failed"
343    ret_code=1
344fi
345
346if grep "arrayIndexThenCheck" ${LOG_FILE} ; then
347    echo "arrayIndexThenCheck check failed"
348    ret_code=1
349fi
350
351if grep "unusedPrivateFunction" ${LOG_FILE} ; then
352    echo "unusedPrivateFunction check failed"
353    ret_code=1
354fi
355
356if grep "redundantCondition" ${LOG_FILE} ; then
357    echo "redundantCondition check failed"
358    ret_code=1
359fi
360
361if grep "unusedStructMember" ${LOG_FILE} | grep -v -e frmts/jpeg/libjpeg -e frmts/gtiff/libtiff -e frmts/zlib ; then
362    echo "unusedStructMember check failed"
363    ret_code=1
364fi
365
366if grep "multiCondition" ${LOG_FILE} ; then
367    echo "multiCondition check failed"
368    ret_code=1
369fi
370
371if grep "duplicateExpression" ${LOG_FILE} ; then
372    echo "duplicateExpression check failed"
373    ret_code=1
374fi
375
376if grep "operatorEq" ${LOG_FILE} ; then
377    echo "operatorEq check failed"
378    ret_code=1
379fi
380
381if grep "truncLongCastAssignment" ${LOG_FILE} ; then
382    echo "truncLongCastAssignment check failed"
383    ret_code=1
384fi
385
386if grep "exceptRethrowCopy" ${LOG_FILE} ; then
387    echo "exceptRethrowCopy check failed"
388    ret_code=1
389fi
390
391if grep "unusedVariable" ${LOG_FILE} ; then
392    echo "unusedVariable check failed"
393    ret_code=1
394fi
395
396if grep "unsafeClassCanLeak" ${LOG_FILE} ; then
397    echo "unsafeClassCanLeak check failed"
398    ret_code=1
399fi
400
401if grep "unsignedLessThanZero" ${LOG_FILE} | grep -v frmts/jpeg/libjpeg ; then
402    echo "unsignedLessThanZero check failed"
403    ret_code=1
404fi
405
406if grep "unpreciseMathCall" ${LOG_FILE} ; then
407    echo "unpreciseMathCall check failed"
408    ret_code=1
409fi
410
411if grep "unreachableCode" ${LOG_FILE} ; then
412    echo "unreachableCode check failed"
413    ret_code=1
414fi
415
416if grep "clarifyCondition" ${LOG_FILE} ; then
417    echo "clarifyCondition check failed"
418    ret_code=1
419fi
420
421if grep "redundantIfRemove" ${LOG_FILE} ; then
422    echo "redundantIfRemove check failed"
423    ret_code=1
424fi
425
426if grep "unassignedVariable" ${LOG_FILE} | grep -v frmts/png/libpng ; then
427    echo "unassignedVariable check failed"
428    ret_code=1
429fi
430
431if grep "redundantAssignment" ${LOG_FILE} | grep -v -e frmts/grib/degrib/g2clib -e frmts/hdf4/hdf-eos -e frmts/png/libpng ; then
432    echo "redundantAssignment check failed"
433    ret_code=1
434fi
435
436if grep "unreadVariable" ${LOG_FILE} | grep -v alg/internal_libqhull | \
437                                    grep -v frmts/gtiff/libtiff  | \
438                                    grep -v frmts/jpeg/libjpeg | \
439                                    grep -v frmts/png/libpng | \
440                                    grep -v frmts/grib/degrib/degrib | \
441                                    grep -v frmts/hdf4/hdf-eos | \
442                                    grep -v frmts/zlib ; then
443    echo "unreadVariable check failed"
444    ret_code=1
445fi
446
447
448for whitelisted_dir in alg/ port/ gcore/; do
449    if grep "cstyleCast" ${LOG_FILE} | grep $whitelisted_dir ; then
450        echo "cstyleCast check failed"
451        ret_code=1
452    fi
453done
454
455if grep "AssignmentAddressToInteger" ${LOG_FILE} ; then
456    echo "AssignmentAddressToInteger check failed"
457    ret_code=1
458fi
459
460
461# Check any remaining errors
462if grep "error," ${LOG_FILE} | grep -v "uninitvar" | \
463    grep -v "memleak," | grep -v "memleakOnRealloc" | \
464    grep -v "frmts/jpeg/libjpeg/jdphuff.c:493,error,shiftNegative,Shifting a negative value is undefined behaviour" | \
465    grep -v "ogr/ogrsf_frmts/avc/avc_bin.c:1866,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds" | \
466    grep -v "frmts/hdf4/hdf-eos/EHapi.c:1890,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
467    grep -v "frmts/hdf4/hdf-eos/EHapi.c:1920,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
468    grep -v "frmts/hdf4/hdf-eos/EHapi.c:1958,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
469    grep -v "frmts/hdf4/hdf-eos/EHapi.c:1994,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
470    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2056,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
471    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2118,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
472    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2159,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
473    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2208,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
474    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2227,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
475    grep -v "frmts/grib/degrib/g2clib" | \
476    grep -v "is invalid C code" ; then
477
478    echo "Errors check failed"
479    ret_code=1
480fi
481
482# Check any remaining warnings
483if grep "warning," ${LOG_FILE} | grep -v "ods_formula_parser" | \
484    grep -v "osr_cs_wkt_parser" | grep -v "swq_parser" | \
485    grep -v "frmts/jpeg/libjpeg" ; then
486    echo "Warnings check failed"
487    ret_code=1
488fi
489
490if [ ${ret_code} = 0 ]; then
491    echo "cppcheck succeeded"
492fi
493
494exit ${ret_code}
495