]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib/clippy: error out on unsupported bits
authorDavid Lamparter <equinox@diac24.net>
Tue, 4 Jun 2019 15:07:57 +0000 (17:07 +0200)
committerDavid Lamparter <equinox@diac24.net>
Wed, 12 Jun 2019 17:22:59 +0000 (19:22 +0200)
clippy can't process #ifdef or similar bits inside of an argument list
(e.g. within the braces of a DEFUN or DEFPY statement.)  Improve error
reporting to catch these cases instead of generating broken C code.

Fixes: #3840
Signed-off-by: David Lamparter <equinox@diac24.net>
lib/clippy.c
lib/defun_lex.l
pimd/pim_cmd.c
python/clidef.py

index 44dcc02eb8645b765a5ee04ccd5a363b8aa45bd7..cd8067f5ebfd34b43b029fa3a864d59198604025 100644 (file)
@@ -85,8 +85,6 @@ int main(int argc, char **argv)
        if (PyRun_AnyFile(fp, pyfile)) {
                if (PyErr_Occurred())
                        PyErr_Print();
-               else
-                       printf("unknown python failure (?)\n");
                return 1;
        }
        Py_Finalize();
index 6c0805a4fa9b4542319eaf82476b35d6bae53698..19b06f51b8d633373a63cb6c4500c8c6d2bad93b 100644 (file)
@@ -163,7 +163,7 @@ static int yylex_clr(char **retbuf)
        return rv;
 }
 
-static PyObject *get_args(void)
+static PyObject *get_args(const char *filename, int lineno)
 {
        PyObject *pyObj = PyList_New(0);
        PyObject *pyArg = NULL;
@@ -190,6 +190,13 @@ static PyObject *get_args(void)
                        free(tval);
                        continue;
                }
+               if (token == PREPROC) {
+                       free(tval);
+                       Py_DECREF(pyObj);
+                       return PyErr_Format(PyExc_ValueError,
+                                       "%s:%d: cannot process CPP directive within argument list",
+                                       filename, lineno);
+               }
                if (token == SPECIAL) {
                        if (depth == 1 && (tval[0] == ',' || tval[0] == ')')) {
                                if (pyArg)
@@ -244,7 +251,12 @@ PyObject *clippy_parse(PyObject *self, PyObject *args)
                case DEFUNNY:
                case INSTALL:
                case AUXILIARY:
-                       pyArgs = get_args();
+                       pyArgs = get_args(filename, lineno);
+                       if (!pyArgs) {
+                               free(tval);
+                               Py_DECREF(pyCont);
+                               return NULL;
+                       }
                        pyItem = PyDict_New();
                        PyDict_SetItemString(pyItem, "type", PyUnicode_FromString(tval));
                        PyDict_SetItemString(pyItem, "args", pyArgs);
@@ -260,6 +272,7 @@ PyObject *clippy_parse(PyObject *self, PyObject *args)
                        pyItem = PyDict_New();
                        PyDict_SetItemString(pyItem, "type", PyUnicode_FromString("PREPROC"));
                        PyDict_SetItemString(pyItem, "line", PyUnicode_FromString(tval));
+                       lineno--;
                        break;
                }
                if (pyItem) {
index 18e84fef23c7b7863abc02888e8da120c5853540..c6617d9d212d451623aafc5bce5e29a30581b7f9 100644 (file)
@@ -8717,9 +8717,17 @@ DEFUN (no_ip_pim_ucast_bsm,
 
 #if HAVE_BFDD > 0
 DEFUN_HIDDEN(
+       ip_pim_bfd_param,
+       ip_pim_bfd_param_cmd,
+       "ip pim bfd (2-255) (50-60000) (50-60000)",
+       IP_STR
+       PIM_STR
+       "Enables BFD support\n"
+       "Detect Multiplier\n"
+       "Required min receive interval\n"
+       "Desired min transmit interval\n")
 #else
 DEFUN(
-#endif /* HAVE_BFDD */
        ip_pim_bfd_param,
        ip_pim_bfd_param_cmd,
        "ip pim bfd (2-255) (50-60000) (50-60000)",
@@ -8729,6 +8737,7 @@ DEFUN(
        "Detect Multiplier\n"
        "Required min receive interval\n"
        "Desired min transmit interval\n")
+#endif /* HAVE_BFDD */
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx_number = 3;
index f8d96115bde887460887e01759129fe36c404f73..68682eea6c2807a4eef42202b7d3529e71d8f08e 100644 (file)
@@ -183,11 +183,25 @@ argblock = Template('''
                }''')
 
 def process_file(fn, ofd, dumpfd, all_defun):
+    errors = 0
     filedata = clippy.parse(fn)
 
     for entry in filedata['data']:
         if entry['type'].startswith('DEFPY') or (all_defun and entry['type'].startswith('DEFUN')):
+            if len(entry['args'][0]) != 1:
+                sys.stderr.write('%s:%d: DEFPY function name not parseable (%r)\n' % (fn, entry['lineno'], entry['args'][0]))
+                errors += 1
+                continue
+
             cmddef = entry['args'][2]
+            for i in cmddef:
+                if not (i.startswith('"') and i.endswith('"')):
+                    sys.stderr.write('%s:%d: DEFPY command string not parseable (%r)\n' % (fn, entry['lineno'], cmddef))
+                    errors += 1
+                    cmddef = None
+                    break
+            if cmddef is None:
+                continue
             cmddef = ''.join([i[1:-1] for i in cmddef])
 
             graph = clippy.Graph(cmddef)
@@ -251,6 +265,8 @@ def process_file(fn, ofd, dumpfd, all_defun):
             params['nonempty'] = len(argblocks)
             ofd.write(templ.substitute(params))
 
+    return errors
+
 if __name__ == '__main__':
     import argparse
 
@@ -274,7 +290,9 @@ if __name__ == '__main__':
         if args.show:
             dumpfd = sys.stderr
 
-    process_file(args.cfile, ofd, dumpfd, args.all_defun)
+    errors = process_file(args.cfile, ofd, dumpfd, args.all_defun)
+    if errors != 0:
+        sys.exit(1)
 
     if args.o is not None:
         clippy.wrdiff(args.o, ofd, [args.cfile, os.path.realpath(__file__), sys.executable])