From b96257d58df1244c5be8b831c390a754fc42d65c Mon Sep 17 00:00:00 2001
From: Andre Maroneze <andre.oliveiramaroneze@cea.fr>
Date: Mon, 14 Jan 2019 10:57:11 +0100
Subject: [PATCH] [Analysis-scripts] improve matching in find-fun, validate
 input, add more tests

---
 share/analysis-scripts/find_fun.py   |  6 +++++-
 tests/fc_script/for-find-fun2.c      | 26 ++++++++++++++++++++++++++
 tests/fc_script/main.c               |  1 +
 tests/fc_script/oracle/find_fun1.res |  2 +-
 tests/fc_script/oracle/find_fun2.res |  4 +++-
 tests/fc_script/oracle/find_fun3.err |  0
 tests/fc_script/oracle/find_fun3.res |  2 ++
 7 files changed, 38 insertions(+), 3 deletions(-)
 create mode 100644 tests/fc_script/for-find-fun2.c
 create mode 100644 tests/fc_script/oracle/find_fun3.err
 create mode 100644 tests/fc_script/oracle/find_fun3.res

diff --git a/share/analysis-scripts/find_fun.py b/share/analysis-scripts/find_fun.py
index 3e89dccbe3b..87c71371312 100755
--- a/share/analysis-scripts/find_fun.py
+++ b/share/analysis-scripts/find_fun.py
@@ -43,6 +43,10 @@ if len(sys.argv) < 2:
    sys.exit(1)
 else:
    fname = sys.argv[1]
+   if re.match('[a-zA-Z_][a-zA-Z0-9_]*$', fname) == None:
+      print("error: function name contains invalid characters: %s" % fname)
+      print("       (only letters/digits/underscore allowed)")
+      sys.exit(1)
 
 dirs = set()
 if len(sys.argv) < 3:
@@ -78,7 +82,7 @@ c_identifier = "[a-zA-Z_][a-zA-Z0-9_]*"
 c_id_maybe_pointer = c_identifier + "\**"
 type_prefix = c_id_maybe_pointer + "(?:\s+\**" + c_id_maybe_pointer + ")*\s+\**"
 parentheses_suffix = "\s*\([^)]*\)"
-re_fun = re.compile("^(?:" + type_prefix + ")?" + fname + parentheses_suffix + "\s*(?:" + c_identifier + ")?\s*(;|{)", flags=re.MULTILINE)
+re_fun = re.compile("^(?:" + type_prefix + "\s*)?" + fname + parentheses_suffix + "\s*(?:" + c_identifier + ")?\s*(;|{)", flags=re.MULTILINE)
 for f in files:
     with open(f, encoding="ascii", errors='ignore') as content_file:
         content = content_file.read()
diff --git a/tests/fc_script/for-find-fun2.c b/tests/fc_script/for-find-fun2.c
new file mode 100644
index 00000000000..3cef634fc5b
--- /dev/null
+++ b/tests/fc_script/for-find-fun2.c
@@ -0,0 +1,26 @@
+/* run.config
+   DONTRUN: test run by main.c
+*/
+
+struct s **	main3(
+                 struct s *p1, struct s s2
+                 )	;
+
+// tests to avoid false positives
+void f() {
+  int (*false_positive)();
+}
+
+void g() {
+  int i = 0;
+  false_positive(i);
+}
+
+void h() {
+  (void)false_positive((int)42);
+}
+
+//void false_positive();
+
+ void false_positive(); // this is a "voluntary" false negative (space before):
+                        // it allows us to avoid false positives more easily
diff --git a/tests/fc_script/main.c b/tests/fc_script/main.c
index 1acc886dfd3..176bf1c3e84 100644
--- a/tests/fc_script/main.c
+++ b/tests/fc_script/main.c
@@ -5,6 +5,7 @@
    EXECNOW: LOG flamegraph.html LOG flamegraph.res LOG flamegraph.err NOGUI=1 bin/frama-c-script flamegraph @PTEST_DIR@/flamegraph.txt @PTEST_DIR@/result > @PTEST_DIR@/result/flamegraph.res 2> @PTEST_DIR@/result/flamegraph.err && rm -f @PTEST_DIR@/result/flamegraph.svg
    EXECNOW: LOG find_fun1.res LOG find_fun1.err bin/frama-c-script find-fun main2 @PTEST_DIR@ > @PTEST_DIR@/result/find_fun1.res 2> @PTEST_DIR@/result/find_fun1.err
    EXECNOW: LOG find_fun2.res LOG find_fun2.err bin/frama-c-script find-fun main3 @PTEST_DIR@ > @PTEST_DIR@/result/find_fun2.res 2> @PTEST_DIR@/result/find_fun2.err
+   EXECNOW: LOG find_fun3.res LOG find_fun3.err bin/frama-c-script find-fun false_positive @PTEST_DIR@ > @PTEST_DIR@/result/find_fun3.res 2> @PTEST_DIR@/result/find_fun3.err
  */
 
 void main() {
diff --git a/tests/fc_script/oracle/find_fun1.res b/tests/fc_script/oracle/find_fun1.res
index 330fcaca0a0..a846b6beb54 100644
--- a/tests/fc_script/oracle/find_fun1.res
+++ b/tests/fc_script/oracle/find_fun1.res
@@ -1,4 +1,4 @@
-Looking for 'main2' inside 4 file(s)...
+Looking for 'main2' inside 5 file(s)...
 Possible declarations for function 'main2' in the following file(s):
   tests/fc_script/for-find-fun.c
 Possible definitions for function 'main2' in the following file(s):
diff --git a/tests/fc_script/oracle/find_fun2.res b/tests/fc_script/oracle/find_fun2.res
index 35e3da577fa..273cc015b4e 100644
--- a/tests/fc_script/oracle/find_fun2.res
+++ b/tests/fc_script/oracle/find_fun2.res
@@ -1,3 +1,5 @@
-Looking for 'main3' inside 4 file(s)...
+Looking for 'main3' inside 5 file(s)...
+Possible declarations for function 'main3' in the following file(s):
+  tests/fc_script/for-find-fun2.c
 Possible definitions for function 'main3' in the following file(s):
   tests/fc_script/for-find-fun.c
diff --git a/tests/fc_script/oracle/find_fun3.err b/tests/fc_script/oracle/find_fun3.err
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/fc_script/oracle/find_fun3.res b/tests/fc_script/oracle/find_fun3.res
new file mode 100644
index 00000000000..a7059bd1c96
--- /dev/null
+++ b/tests/fc_script/oracle/find_fun3.res
@@ -0,0 +1,2 @@
+Looking for 'false_positive' inside 5 file(s)...
+No declaration/definition found for function 'false_positive'
-- 
GitLab