18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci///
38c2ecf20Sopenharmony_ci/// Find if/else condition with kmalloc/vmalloc calls.
48c2ecf20Sopenharmony_ci/// Suggest to use kvmalloc instead. Same for kvfree.
58c2ecf20Sopenharmony_ci///
68c2ecf20Sopenharmony_ci// Confidence: High
78c2ecf20Sopenharmony_ci// Copyright: (C) 2020 Denis Efremov ISPRAS
88c2ecf20Sopenharmony_ci// Options: --no-includes --include-headers
98c2ecf20Sopenharmony_ci//
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_civirtual patch
128c2ecf20Sopenharmony_civirtual report
138c2ecf20Sopenharmony_civirtual org
148c2ecf20Sopenharmony_civirtual context
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci@initialize:python@
178c2ecf20Sopenharmony_ci@@
188c2ecf20Sopenharmony_cifilter = frozenset(['kvfree'])
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cidef relevant(p):
218c2ecf20Sopenharmony_ci    return not (filter & {el.current_element for el in p})
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci@kvmalloc depends on !patch@
248c2ecf20Sopenharmony_ciexpression E, E1, size;
258c2ecf20Sopenharmony_ciidentifier flags;
268c2ecf20Sopenharmony_cibinary operator cmp = {<=, <, ==, >, >=};
278c2ecf20Sopenharmony_ciidentifier x;
288c2ecf20Sopenharmony_citype T;
298c2ecf20Sopenharmony_ciposition p;
308c2ecf20Sopenharmony_ci@@
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci(
338c2ecf20Sopenharmony_ci* if (size cmp E1 || ...)@p {
348c2ecf20Sopenharmony_ci    ...
358c2ecf20Sopenharmony_ci*    E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
368c2ecf20Sopenharmony_ci*          kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
378c2ecf20Sopenharmony_ci*          (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...)
388c2ecf20Sopenharmony_ci    ...
398c2ecf20Sopenharmony_ci  } else {
408c2ecf20Sopenharmony_ci    ...
418c2ecf20Sopenharmony_ci*    E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
428c2ecf20Sopenharmony_ci    ...
438c2ecf20Sopenharmony_ci  }
448c2ecf20Sopenharmony_ci|
458c2ecf20Sopenharmony_ci* E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
468c2ecf20Sopenharmony_ci*       kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
478c2ecf20Sopenharmony_ci*       (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...)
488c2ecf20Sopenharmony_ci  ... when != E = E1
498c2ecf20Sopenharmony_ci      when != size = E1
508c2ecf20Sopenharmony_ci      when any
518c2ecf20Sopenharmony_ci* if (E == NULL)@p {
528c2ecf20Sopenharmony_ci    ...
538c2ecf20Sopenharmony_ci*   E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
548c2ecf20Sopenharmony_ci    ...
558c2ecf20Sopenharmony_ci  }
568c2ecf20Sopenharmony_ci|
578c2ecf20Sopenharmony_ci* T x = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\|
588c2ecf20Sopenharmony_ci*         kmalloc_array\|kmalloc_array_node\|kcalloc_node\)
598c2ecf20Sopenharmony_ci*         (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...);
608c2ecf20Sopenharmony_ci  ... when != x = E1
618c2ecf20Sopenharmony_ci      when != size = E1
628c2ecf20Sopenharmony_ci      when any
638c2ecf20Sopenharmony_ci* if (x == NULL)@p {
648c2ecf20Sopenharmony_ci    ...
658c2ecf20Sopenharmony_ci*   x = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...)
668c2ecf20Sopenharmony_ci    ...
678c2ecf20Sopenharmony_ci  }
688c2ecf20Sopenharmony_ci)
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci@kvfree depends on !patch@
718c2ecf20Sopenharmony_ciexpression E;
728c2ecf20Sopenharmony_ciposition p : script:python() { relevant(p) };
738c2ecf20Sopenharmony_ci@@
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci* if (is_vmalloc_addr(E))@p {
768c2ecf20Sopenharmony_ci    ...
778c2ecf20Sopenharmony_ci*   vfree(E)
788c2ecf20Sopenharmony_ci    ...
798c2ecf20Sopenharmony_ci  } else {
808c2ecf20Sopenharmony_ci    ... when != krealloc(E, ...)
818c2ecf20Sopenharmony_ci        when any
828c2ecf20Sopenharmony_ci*   \(kfree\|kzfree\)(E)
838c2ecf20Sopenharmony_ci    ...
848c2ecf20Sopenharmony_ci  }
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci@depends on patch@
878c2ecf20Sopenharmony_ciexpression E, E1, size, node;
888c2ecf20Sopenharmony_cibinary operator cmp = {<=, <, ==, >, >=};
898c2ecf20Sopenharmony_ciidentifier flags, x;
908c2ecf20Sopenharmony_citype T;
918c2ecf20Sopenharmony_ci@@
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci(
948c2ecf20Sopenharmony_ci- if (size cmp E1)
958c2ecf20Sopenharmony_ci-    E = kmalloc(size, flags);
968c2ecf20Sopenharmony_ci- else
978c2ecf20Sopenharmony_ci-    E = vmalloc(size);
988c2ecf20Sopenharmony_ci+ E = kvmalloc(size, flags);
998c2ecf20Sopenharmony_ci|
1008c2ecf20Sopenharmony_ci- if (size cmp E1)
1018c2ecf20Sopenharmony_ci-    E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
1028c2ecf20Sopenharmony_ci- else
1038c2ecf20Sopenharmony_ci-    E = vmalloc(size);
1048c2ecf20Sopenharmony_ci+ E = kvmalloc(size, GFP_KERNEL);
1058c2ecf20Sopenharmony_ci|
1068c2ecf20Sopenharmony_ci- E = kmalloc(size, flags | __GFP_NOWARN);
1078c2ecf20Sopenharmony_ci- if (E == NULL)
1088c2ecf20Sopenharmony_ci-   E = vmalloc(size);
1098c2ecf20Sopenharmony_ci+ E = kvmalloc(size, flags);
1108c2ecf20Sopenharmony_ci|
1118c2ecf20Sopenharmony_ci- E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
1128c2ecf20Sopenharmony_ci- if (E == NULL)
1138c2ecf20Sopenharmony_ci-   E = vmalloc(size);
1148c2ecf20Sopenharmony_ci+ E = kvmalloc(size, GFP_KERNEL);
1158c2ecf20Sopenharmony_ci|
1168c2ecf20Sopenharmony_ci- T x = kmalloc(size, flags | __GFP_NOWARN);
1178c2ecf20Sopenharmony_ci- if (x == NULL)
1188c2ecf20Sopenharmony_ci-   x = vmalloc(size);
1198c2ecf20Sopenharmony_ci+ T x = kvmalloc(size, flags);
1208c2ecf20Sopenharmony_ci|
1218c2ecf20Sopenharmony_ci- T x = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
1228c2ecf20Sopenharmony_ci- if (x == NULL)
1238c2ecf20Sopenharmony_ci-   x = vmalloc(size);
1248c2ecf20Sopenharmony_ci+ T x = kvmalloc(size, GFP_KERNEL);
1258c2ecf20Sopenharmony_ci|
1268c2ecf20Sopenharmony_ci- if (size cmp E1)
1278c2ecf20Sopenharmony_ci-    E = kzalloc(size, flags);
1288c2ecf20Sopenharmony_ci- else
1298c2ecf20Sopenharmony_ci-    E = vzalloc(size);
1308c2ecf20Sopenharmony_ci+ E = kvzalloc(size, flags);
1318c2ecf20Sopenharmony_ci|
1328c2ecf20Sopenharmony_ci- if (size cmp E1)
1338c2ecf20Sopenharmony_ci-    E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
1348c2ecf20Sopenharmony_ci- else
1358c2ecf20Sopenharmony_ci-    E = vzalloc(size);
1368c2ecf20Sopenharmony_ci+ E = kvzalloc(size, GFP_KERNEL);
1378c2ecf20Sopenharmony_ci|
1388c2ecf20Sopenharmony_ci- E = kzalloc(size, flags | __GFP_NOWARN);
1398c2ecf20Sopenharmony_ci- if (E == NULL)
1408c2ecf20Sopenharmony_ci-   E = vzalloc(size);
1418c2ecf20Sopenharmony_ci+ E = kvzalloc(size, flags);
1428c2ecf20Sopenharmony_ci|
1438c2ecf20Sopenharmony_ci- E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
1448c2ecf20Sopenharmony_ci- if (E == NULL)
1458c2ecf20Sopenharmony_ci-   E = vzalloc(size);
1468c2ecf20Sopenharmony_ci+ E = kvzalloc(size, GFP_KERNEL);
1478c2ecf20Sopenharmony_ci|
1488c2ecf20Sopenharmony_ci- T x = kzalloc(size, flags | __GFP_NOWARN);
1498c2ecf20Sopenharmony_ci- if (x == NULL)
1508c2ecf20Sopenharmony_ci-   x = vzalloc(size);
1518c2ecf20Sopenharmony_ci+ T x = kvzalloc(size, flags);
1528c2ecf20Sopenharmony_ci|
1538c2ecf20Sopenharmony_ci- T x = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\));
1548c2ecf20Sopenharmony_ci- if (x == NULL)
1558c2ecf20Sopenharmony_ci-   x = vzalloc(size);
1568c2ecf20Sopenharmony_ci+ T x = kvzalloc(size, GFP_KERNEL);
1578c2ecf20Sopenharmony_ci|
1588c2ecf20Sopenharmony_ci- if (size cmp E1)
1598c2ecf20Sopenharmony_ci-    E = kmalloc_node(size, flags, node);
1608c2ecf20Sopenharmony_ci- else
1618c2ecf20Sopenharmony_ci-    E = vmalloc_node(size, node);
1628c2ecf20Sopenharmony_ci+ E = kvmalloc_node(size, flags, node);
1638c2ecf20Sopenharmony_ci|
1648c2ecf20Sopenharmony_ci- if (size cmp E1)
1658c2ecf20Sopenharmony_ci-    E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
1668c2ecf20Sopenharmony_ci- else
1678c2ecf20Sopenharmony_ci-    E = vmalloc_node(size, node);
1688c2ecf20Sopenharmony_ci+ E = kvmalloc_node(size, GFP_KERNEL, node);
1698c2ecf20Sopenharmony_ci|
1708c2ecf20Sopenharmony_ci- E = kmalloc_node(size, flags | __GFP_NOWARN, node);
1718c2ecf20Sopenharmony_ci- if (E == NULL)
1728c2ecf20Sopenharmony_ci-   E = vmalloc_node(size, node);
1738c2ecf20Sopenharmony_ci+ E = kvmalloc_node(size, flags, node);
1748c2ecf20Sopenharmony_ci|
1758c2ecf20Sopenharmony_ci- E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
1768c2ecf20Sopenharmony_ci- if (E == NULL)
1778c2ecf20Sopenharmony_ci-   E = vmalloc_node(size, node);
1788c2ecf20Sopenharmony_ci+ E = kvmalloc_node(size, GFP_KERNEL, node);
1798c2ecf20Sopenharmony_ci|
1808c2ecf20Sopenharmony_ci- T x = kmalloc_node(size, flags | __GFP_NOWARN, node);
1818c2ecf20Sopenharmony_ci- if (x == NULL)
1828c2ecf20Sopenharmony_ci-   x = vmalloc_node(size, node);
1838c2ecf20Sopenharmony_ci+ T x = kvmalloc_node(size, flags, node);
1848c2ecf20Sopenharmony_ci|
1858c2ecf20Sopenharmony_ci- T x = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
1868c2ecf20Sopenharmony_ci- if (x == NULL)
1878c2ecf20Sopenharmony_ci-   x = vmalloc_node(size, node);
1888c2ecf20Sopenharmony_ci+ T x = kvmalloc_node(size, GFP_KERNEL, node);
1898c2ecf20Sopenharmony_ci|
1908c2ecf20Sopenharmony_ci- if (size cmp E1)
1918c2ecf20Sopenharmony_ci-    E = kvzalloc_node(size, flags, node);
1928c2ecf20Sopenharmony_ci- else
1938c2ecf20Sopenharmony_ci-    E = vzalloc_node(size, node);
1948c2ecf20Sopenharmony_ci+ E = kvzalloc_node(size, flags, node);
1958c2ecf20Sopenharmony_ci|
1968c2ecf20Sopenharmony_ci- if (size cmp E1)
1978c2ecf20Sopenharmony_ci-    E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
1988c2ecf20Sopenharmony_ci- else
1998c2ecf20Sopenharmony_ci-    E = vzalloc_node(size, node);
2008c2ecf20Sopenharmony_ci+ E = kvzalloc_node(size, GFP_KERNEL, node);
2018c2ecf20Sopenharmony_ci|
2028c2ecf20Sopenharmony_ci- E = kvzalloc_node(size, flags | __GFP_NOWARN, node);
2038c2ecf20Sopenharmony_ci- if (E == NULL)
2048c2ecf20Sopenharmony_ci-   E = vzalloc_node(size, node);
2058c2ecf20Sopenharmony_ci+ E = kvzalloc_node(size, flags, node);
2068c2ecf20Sopenharmony_ci|
2078c2ecf20Sopenharmony_ci- E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
2088c2ecf20Sopenharmony_ci- if (E == NULL)
2098c2ecf20Sopenharmony_ci-   E = vzalloc_node(size, node);
2108c2ecf20Sopenharmony_ci+ E = kvzalloc_node(size, GFP_KERNEL, node);
2118c2ecf20Sopenharmony_ci|
2128c2ecf20Sopenharmony_ci- T x = kvzalloc_node(size, flags | __GFP_NOWARN, node);
2138c2ecf20Sopenharmony_ci- if (x == NULL)
2148c2ecf20Sopenharmony_ci-   x = vzalloc_node(size, node);
2158c2ecf20Sopenharmony_ci+ T x = kvzalloc_node(size, flags, node);
2168c2ecf20Sopenharmony_ci|
2178c2ecf20Sopenharmony_ci- T x = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node);
2188c2ecf20Sopenharmony_ci- if (x == NULL)
2198c2ecf20Sopenharmony_ci-   x = vzalloc_node(size, node);
2208c2ecf20Sopenharmony_ci+ T x = kvzalloc_node(size, GFP_KERNEL, node);
2218c2ecf20Sopenharmony_ci)
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci@depends on patch@
2248c2ecf20Sopenharmony_ciexpression E;
2258c2ecf20Sopenharmony_ciposition p : script:python() { relevant(p) };
2268c2ecf20Sopenharmony_ci@@
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci- if (is_vmalloc_addr(E))@p
2298c2ecf20Sopenharmony_ci-   vfree(E);
2308c2ecf20Sopenharmony_ci- else
2318c2ecf20Sopenharmony_ci-   kfree(E);
2328c2ecf20Sopenharmony_ci+ kvfree(E);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci@script: python depends on report@
2358c2ecf20Sopenharmony_cip << kvmalloc.p;
2368c2ecf20Sopenharmony_ci@@
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cicoccilib.report.print_report(p[0], "WARNING opportunity for kvmalloc")
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci@script: python depends on org@
2418c2ecf20Sopenharmony_cip << kvmalloc.p;
2428c2ecf20Sopenharmony_ci@@
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_cicoccilib.org.print_todo(p[0], "WARNING opportunity for kvmalloc")
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci@script: python depends on report@
2478c2ecf20Sopenharmony_cip << kvfree.p;
2488c2ecf20Sopenharmony_ci@@
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_cicoccilib.report.print_report(p[0], "WARNING opportunity for kvfree")
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci@script: python depends on org@
2538c2ecf20Sopenharmony_cip << kvfree.p;
2548c2ecf20Sopenharmony_ci@@
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_cicoccilib.org.print_todo(p[0], "WARNING opportunity for kvfree")
257