Browse Source

CI: Introduce Smatch for static analysis (#125)

Smatch[1][2] is a pluggable static analysis for C. It may help us find
out the potential problem of the example code.

Doing with smatch, if set the --file-output flag, it will generate the
{}.c.smatch report for each c file. This will make a little bit
complicated to collect all the report messages. So, here we stay at the
default setting, stdout for the smatch messages.

For more information, see:
- https://lwn.net/Articles/696624/
- https://elinux.org/images/d/d3/Bargmann.pdf

Also, fix the warning from Smatch:

Smatch failed: 1 warning(s), 1 error(s)
lkmpg/examples/procfs2.c:57 procfile_write() error: buffer overflow 'procfs_buffer' 1024 <= 1024
lkmpg/examples/kbleds.c:58 kbleds_init() warn: argument 5 to %lx specifier is cast from pointer

Furthermore, the effect of the write operation in procfs2.c is too
implied. So after writing, print the buffer every time.

Close #122

[1] https://github.com/error27/smatch
[2] https://repo.or.cz/w/smatch.git
linD026 3 years ago
parent
commit
6b6b6635cf
3 changed files with 33 additions and 4 deletions
  1. 28 1
      .ci/static-analysis.sh
  2. 2 2
      examples/kbleds.c
  3. 3 1
      examples/procfs2.c

+ 28 - 1
.ci/static-analysis.sh

@@ -46,8 +46,9 @@ function do_sparse()
     make sparse || exit 1
     sudo make INST_PROGRAMS=sparse PREFIX=/usr install || exit 1
     popd
+    local SPARSE=$(which sparse)
 
-    make -C examples C=2 2> sparse.log
+    make -C examples C=2 CHECK="$SPARSE" 2> sparse.log
 
     local WARNING_COUNT=$(cat sparse.log | egrep -c " warning:" )
     local ERROR_COUNT=$(cat sparse.log | egrep -c " error:" )
@@ -81,7 +82,33 @@ function do_gcc()
     make -C examples CONFIG_STATUS_CHECK_GCC=y STATUS_CHECK_GCC=$GCC clean
 }
 
+function do_smatch()
+{
+    wget -q https://repo.or.cz/smatch.git/snapshot/refs/heads/master.tar.gz
+    if [ $? -ne 0 ]; then
+        echo "Failed to download smatch."
+        exit 1
+    fi
+    tar -xzf master.tar.gz
+    pushd smatch-master-*
+    make smatch || exit 1
+    local SMATCH=$(pwd)/smatch
+    popd
+
+    make -C examples C=2 CHECK="$SMATCH -p=kernel" > smatch.log
+    local WARNING_COUNT=$(cat smatch.log | egrep -c " warn:" )
+    local ERROR_COUNT=$(cat smatch.log | egrep -c " error:" )
+    local COUNT=`expr $WARNING_COUNT + $ERROR_COUNT`
+    if [ $COUNT -gt 0 ]; then
+        echo "Smatch failed: $WARNING_COUNT warning(s), $ERROR_COUNT error(s)"
+        cat smatch.log | grep "warn:\|error:"
+        exit 1
+    fi
+    make -C examples clean
+}
+
 do_cppcheck
 do_sparse
 do_gcc
+do_smatch
 exit 0

+ 2 - 2
examples/kbleds.c

@@ -55,8 +55,8 @@ static int __init kbleds_init(void)
     for (i = 0; i < MAX_NR_CONSOLES; i++) {
         if (!vc_cons[i].d)
             break;
-        pr_info("poet_atkm: console[%i/%i] #%i, tty %lx\n", i, MAX_NR_CONSOLES,
-                vc_cons[i].d->vc_num, (unsigned long)vc_cons[i].d->port.tty);
+        pr_info("poet_atkm: console[%i/%i] #%i, tty %p\n", i, MAX_NR_CONSOLES,
+                vc_cons[i].d->vc_num, (void *)vc_cons[i].d->port.tty);
     }
     pr_info("kbleds: finished scanning consoles\n");
 

+ 3 - 1
examples/procfs2.c

@@ -54,7 +54,9 @@ static ssize_t procfile_write(struct file *file, const char __user *buff,
     if (copy_from_user(procfs_buffer, buff, procfs_buffer_size))
         return -EFAULT;
 
-    procfs_buffer[procfs_buffer_size] = '\0';
+    procfs_buffer[procfs_buffer_size & (PROCFS_MAX_SIZE - 1)] = '\0';
+    pr_info("procfile write %s\n", procfs_buffer);
+
     return procfs_buffer_size;
 }