C-Splint

Step 1 : Install splint - Static analyser

$ sudo apt-get install splint
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  g++-7 gcc-8-base:i386 gir1.2-mutter-2 libargon2-0 libbind9-160 libbison-dev libboost-date-time1.65.1 libboost-filesystem1.65.1 libboost-iostreams1.65.1
  libboost-locale1.65.1 libboost-system1.65.1 libboost-thread1.65.1 libcapnp-0.6.1 libcdio17 libclang1-6.0 libcomerr2:i386 libcommons-dbcp-java libcommons-pool-java
  libcwidget3v5 libdns-export1100 libdns1100 libdouble-conversion1 libecj-java libevent-2.1-6 libffi6:i386 libgdbm5 libgl1-mesa-glx:i386 libgmime-3.0-0
  libgnome-desktop-3-17 libgspell-1-1 libgweather-3-15 libhogweed4:i386 libhunspell-1.6-0 libicu60:i386 libip4tc0 libip6tc0 libiptc0 libirs-export160 libirs160
  libisc-export169 libisc169 libisccc160 libisccfg-export160 libisccfg160 libisl19 libjs-sphinxdoc libjs-underscore libjson-c3 liblinear3 libllvm10:i386 libllvm11
  libllvm11:i386 libllvm6.0 liblouis14 liblouisutdml8 liblwres160 libmagickcore-6.q16-3 libmagickcore-6.q16-3-extra libmagickwand-6.q16-3 libmozjs-52-0
  libmutter-2-0 libncurses5:i386 libnettle6:i386 libnss-myhostname libntfs-3g88 liborcus-0.13-0 libperl5.26 libpoppler73 libpotrace0 libprocps6 libprotobuf-lite10
  libprotobuf10 libprotoc10 libpython-all-dev libpython3.6 libpython3.6-dev libpython3.6-minimal libpython3.6-stdlib libqgsttools-p1 libqpdf21 libraw16 libreadline7
  libruby2.5 libsane1 libsane1:i386 libsndio6.1:i386 libspeexdsp1:i386 libstdc++-7-dev libsynctex1 libtexlua52 libtinfo5:i386 libtomcat8-java libvpx5 libwireshark11
  libwiretap8 libwscodecs2 libwsutil9 linux-cloud-tools-5.4.0-88 linux-cloud-tools-5.4.0-88-generic linux-headers-5.4.0-88 linux-headers-5.4.0-88-generic
  linux-image-5.4.0-88-generic linux-modules-5.4.0-88-generic linux-modules-extra-5.4.0-88-generic linux-tools-5.4.0-88 linux-tools-5.4.0-88-generic nplan
  python-all python-all-dev python-asn1crypto python-bzrlib python-cffi-backend python-configobj python-configparser python-crypto python-cryptography
  python-entrypoints python-enum34 python-httplib2 python-idna python-ipaddress python-keyring python-launchpadlib python-lazr.restfulclient python-lazr.uri
  python-oauth python-pycurl python-secretstorage python-simplejson python-wadllib python-wheel python-xdg python-zope.interface python3-asn1crypto python3-oauth
  python3-zope.interface python3.6 python3.6-dev python3.6-minimal ruby-did-you-mean ruby2.5 shim wireshark-gtk
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  splint-data
Suggested packages:
  splint-doc-html
The following NEW packages will be installed:
  splint splint-data
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 740 kB of archives.
After this operation, 2,883 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
Get:1 http://in.archive.ubuntu.com/ubuntu focal/universe amd64 splint-data all 1:3.1.2+dfsg-1build1 [57.5 kB]
Get:2 http://in.archive.ubuntu.com/ubuntu focal/universe amd64 splint amd64 1:3.1.2+dfsg-1build1 [683 kB]
Fetched 740 kB in 1s (808 kB/s) 
Selecting previously unselected package splint-data.
(Reading database ... 461017 files and directories currently installed.)
Preparing to unpack .../splint-data_1%3a3.1.2+dfsg-1build1_all.deb ...
Unpacking splint-data (1:3.1.2+dfsg-1build1) ...
Selecting previously unselected package splint.
Preparing to unpack .../splint_1%3a3.1.2+dfsg-1build1_amd64.deb ...
Unpacking splint (1:3.1.2+dfsg-1build1) ...
Setting up splint-data (1:3.1.2+dfsg-1build1) ...
Setting up splint (1:3.1.2+dfsg-1build1) ...
Processing triggers for man-db (2.9.1-1) ...

Step 2 : Create a file test.c with programming mistake

#include <stdio.h>
#include <stdlib.h>

void fun_2()
{
	int a[5] = {1,2,3,4,5};
	int *p = a;

	a[5] = 400;
	a[6] = 400;
}

void fun_1()
{
	int a[5] = {1,2,3,4,5};
	int *p;

	p += 3;

	*p = 100;

	p += 3;

	*p = 200;
}

int main()
{
  char *p;

  // Allocation #1 of 30 bytes
  p = (char *) malloc(30);

  // Allocation #2 of 12 bytes
  p = (char *) malloc(8);

  // Allocation #3 of 16 bytes
  p = (char *) malloc(25);
  free(p);

  return 0;
}

Step 3 : Run splint on test.c to do Static analysis

$ splint test.c 
Splint 3.1.2 --- 20 Feb 2018

test.c: (in function fun_2)
test.c:7:7: Variable p declared but not used
  A variable is declared but never used. Use /*@unused@*/ in front of
  declaration to suppress message. (Use -varuse to inhibit warning)
test.c: (in function fun_1)
test.c:18:2: Variable p used before definition
  An rvalue is used that may not be initialized to a value on some execution
  path. (Use -usedef to inhibit warning)
test.c:15:6: Variable a declared but not used
test.c: (in function main)
test.c:35:3: Fresh storage p (type char *) not released before assignment:
                p = (char *)malloc(8)
  A memory leak has been detected. Storage allocated locally is not released
  before the last reference to it is lost. (Use -mustfreefresh to inhibit
  warning)
   test.c:32:3: Fresh storage p created
test.c:38:3: Fresh storage p (type char *) not released before assignment:
                p = (char *)malloc(25)
   test.c:35:3: Fresh storage p created

Finished checking --- 5 code warnings

Step 4 : Fix Programming mistakes in file test.c and check splint

#include <stdio.h>
#include <stdlib.h>

void fun_2()
{
	int a[5] = {1,2,3,4,5};
	int *p = a;

	a[5] = 400;
	a[6] = 400;
	*p = 100;
}

void fun_1()
{
	int a[5] = {1,2,3,4,5};
	int *p = a;

	p += 3;

	*p = 100;

	p += 3;

	*p = 200;
}

int main()
{
  char *p;

  // Allocation #1 of 30 bytes
  p = (char *) malloc(30);
  free(p);

  // Allocation #2 of 12 bytes
  p = (char *) malloc(8);
  free(p);

  // Allocation #3 of 16 bytes
  p = (char *) malloc(25);
  free(p);

  return 0;
}

Step 5 : Run splint on test.c to do Static analysis

$ splint test.c 
Splint 3.1.2 --- 20 Feb 2018

Finished checking --- no warnings