// A pci_get_slot or related function is not matched by a // pci_put_slot before an error return. // // Confidence: Moderate // Copyright: (C) Gilles Muller, Julia Lawall, EMN, INRIA, DIKU. GPLv2. // URL: https://coccinelle.gitlabpages.inria.fr/website/rules/get_slot.html // Options: @r@ local idexpression n; position p1; @@ n = \(pci_get_slot@p1\|pci_get_device@p1\|pci_get_bus_and_slot@p1\)(...) // find the missing returns @t exists@ local idexpression n; statement S1; expression E; expression *ptr != NULL; type T; position r.p1,p2; @@ ( if ((n = \(pci_get_slot@p1\|pci_get_device@p1\|pci_get_bus_and_slot@p1\)(...)) == NULL) S1 | n = \(pci_get_slot@p1\|pci_get_device@p1\|pci_get_bus_and_slot@p1\)(...) ) ... when != pci_dev_put(n) when != if (...) { <+... pci_dev_put(n) ...+> } when != true n == NULL || ... when != n = (T)E when != E = n ( return \(0\|<+...n...+>\|ptr\); | return@p2 ...; ) // find the ones with no inconsistent paths @s@ local idexpression n; statement S1,S2; expression E,E1; expression *ptr != NULL; type T,T1; identifier l1,l2; position r.p1; @@ ( if ((n = \(pci_get_slot@p1\|pci_get_device@p1\|pci_get_bus_and_slot@p1\)(...)) == NULL) S1 | n = \(pci_get_slot@p1\|pci_get_device@p1\|pci_get_bus_and_slot@p1\)(...) ) <... when != pci_dev_put(n) when != if (...) { <+... pci_dev_put(n) ...+> } when != true n == NULL || ... when != n = (T)E when != E = n when != goto l1; if (n == NULL || ...) S2 ...> ( return \(0\|<+...n...+>\|ptr\); | + pci_dev_put(n); return ...; | pci_dev_put(n); | n = (T1)E1 | E1 = n | goto l2; ) @script:python depends on !s@ p1 << r.p1; p2 << t.p2; @@ print "* file: %s pci_get_slot/pci_get_device/pci_get_bus_and_slot %s return %s" % (p1[0].file,p1[0].line,p2[0].line)