// Copyright © 2009 Red Hat, Inc. // // This software is licensed to you under the GNU Lesser General Public // License, version 2.1 (LGPLv2.1). There is NO WARRANTY for this software, // express or implied, including the implied warranties of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of // LGPLv2.1 along with this software; if not, see // http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt // // Red Hat trademarks are not licensed under LGPLv2.1. No permission is // granted to use or replicate Red Hat trademarks that are incorporated in // this software or its documentation. // // Red Hat Author(s): David Hugh Malcolm @initialize:python@ """ Analyze format strings passed to variadic function, compare to vararg types actually passed FIXME: generalize this to arbitrary number of varargs; how to express this in SmPL? """ import sys sys.path.append('.') from validate import validate_types num_errors = 0 @ check_PyArg_ParseTuple_1 @ position pos; expression args; expression fmt; type t1; t1 e1; @@ PyArg_ParseTuple@pos(args, fmt, e1) @script:python@ pos << check_PyArg_ParseTuple_1.pos; fmt << check_PyArg_ParseTuple_1.fmt; t1 << check_PyArg_ParseTuple_1.t1; @@ # For some reason, locations are coming as a 1-tuple containing a Location (from # coccilibs.elems), rather than the location itself # Hence we use p1[0], not p1 num_errors += validate_types(pos[0], fmt.expr, [t1]) @ check_PyArg_ParseTuple_2 @ position pos; expression args; expression fmt; type t1; t1 e1; type t2; t2 e2; @@ PyArg_ParseTuple(args@pos, fmt, e1, e2) @script:python@ fmt << check_PyArg_ParseTuple_2.fmt; pos << check_PyArg_ParseTuple_2.pos; t1 << check_PyArg_ParseTuple_2.t1; t2 << check_PyArg_ParseTuple_2.t2; @@ num_errors += validate_types(pos[0], fmt.expr, [t1, t2]) @ check_PyArg_ParseTuple_3 @ position pos; expression args; expression fmt; type t1; t1 e1; type t2; t2 e2; type t3; t3 e3; @@ PyArg_ParseTuple(args@pos, fmt, e1, e2, e3) @script:python@ pos << check_PyArg_ParseTuple_3.pos; fmt << check_PyArg_ParseTuple_3.fmt; pos << check_PyArg_ParseTuple_3.pos; t1 << check_PyArg_ParseTuple_3.t1; t2 << check_PyArg_ParseTuple_3.t2; t3 << check_PyArg_ParseTuple_3.t3; @@ num_errors += validate_types(pos[0], fmt.expr, [t1, t2, t3]) # and so on... need to find a general way of doing this, rather than repeating for 4, 5, 6... # likewise for PyArg_Parse: @ check_PyArg_Parse_1 @ position pos; expression args; expression fmt; type t1; t1 e1; @@ PyArg_Parse@pos(args, fmt, e1) @script:python@ pos << check_PyArg_Parse_1.pos; args << check_PyArg_Parse_1.args; fmt << check_PyArg_Parse_1.fmt; pos << check_PyArg_Parse_1.pos; t1 << check_PyArg_Parse_1.t1; @@ num_errors += validate_types(pos[0], fmt.expr, [t1]) # again, for all N # similarly for PyArg_ParseTupleAndKeywords: @ check_PyArg_ParseTupleAndKeywords_1 @ position pos; expression args, kw, fmt, keywords; type t1; t1 e1; @@ PyArg_ParseTupleAndKeywords@pos(args, kw, fmt, keywords, e1) @script:python@ pos << check_PyArg_Parse_1.pos; args << check_PyArg_Parse_1.args; fmt << check_PyArg_Parse_1.fmt; pos << check_PyArg_Parse_1.pos; t1 << check_PyArg_Parse_1.t1; @@ num_errors += validate_types(pos[0], fmt.expr, [t1]) # etc @script:python @ @@ # Shutdown hook: report the number of errors for use in Makefiles etc: sys.exit(num_errors)