1// SPDX-License-Identifier: GPL-2.0-only 2/// 3/// Check for array_size(), array3_size(), struct_size() duplicates. 4/// These patterns are detected: 5/// 1. An opencoded expression is used before array_size() to compute the same size 6/// 2. An opencoded expression is used after array_size() to compute the same size 7/// From security point of view only first case is relevant. These functions 8/// perform arithmetic overflow check. Thus, if we use an opencoded expression 9/// before a call to the *_size() function we can miss an overflow. 10/// 11// Confidence: High 12// Copyright: (C) 2020 Denis Efremov ISPRAS 13// Options: --no-includes --include-headers --no-loops 14 15virtual context 16virtual report 17virtual org 18 19@as@ 20expression E1, E2; 21@@ 22 23array_size(E1, E2) 24 25@as_next@ 26expression subE1 <= as.E1; 27expression subE2 <= as.E2; 28expression as.E1, as.E2, E3; 29assignment operator aop; 30position p1, p2; 31@@ 32 33* E1 * E2@p1 34 ... when != \(subE1\|subE2\) aop E3 35 when != &\(subE1\|subE2\) 36* array_size(E1, E2)@p2 37 38@script:python depends on report@ 39p1 << as_next.p1; 40p2 << as_next.p2; 41@@ 42 43msg = "WARNING: array_size is used later (line %s) to compute the same size" % (p2[0].line) 44coccilib.report.print_report(p1[0], msg) 45 46@script:python depends on org@ 47p1 << as_next.p1; 48p2 << as_next.p2; 49@@ 50 51msg = "WARNING: array_size is used later (line %s) to compute the same size" % (p2[0].line) 52coccilib.org.print_todo(p1[0], msg) 53 54@as_prev@ 55expression subE1 <= as.E1; 56expression subE2 <= as.E2; 57expression as.E1, as.E2, E3; 58assignment operator aop; 59position p1, p2; 60@@ 61 62* array_size(E1, E2)@p1 63 ... when != \(subE1\|subE2\) aop E3 64 when != &\(subE1\|subE2\) 65* E1 * E2@p2 66 67@script:python depends on report@ 68p1 << as_prev.p1; 69p2 << as_prev.p2; 70@@ 71 72msg = "WARNING: array_size is already used (line %s) to compute the same size" % (p1[0].line) 73coccilib.report.print_report(p2[0], msg) 74 75@script:python depends on org@ 76p1 << as_prev.p1; 77p2 << as_prev.p2; 78@@ 79 80msg = "WARNING: array_size is already used (line %s) to compute the same size" % (p1[0].line) 81coccilib.org.print_todo(p2[0], msg) 82 83@as3@ 84expression E1, E2, E3; 85@@ 86 87array3_size(E1, E2, E3) 88 89@as3_next@ 90expression subE1 <= as3.E1; 91expression subE2 <= as3.E2; 92expression subE3 <= as3.E3; 93expression as3.E1, as3.E2, as3.E3, E4; 94assignment operator aop; 95position p1, p2; 96@@ 97 98* E1 * E2 * E3@p1 99 ... when != \(subE1\|subE2\|subE3\) aop E4 100 when != &\(subE1\|subE2\|subE3\) 101* array3_size(E1, E2, E3)@p2 102 103@script:python depends on report@ 104p1 << as3_next.p1; 105p2 << as3_next.p2; 106@@ 107 108msg = "WARNING: array3_size is used later (line %s) to compute the same size" % (p2[0].line) 109coccilib.report.print_report(p1[0], msg) 110 111@script:python depends on org@ 112p1 << as3_next.p1; 113p2 << as3_next.p2; 114@@ 115 116msg = "WARNING: array3_size is used later (line %s) to compute the same size" % (p2[0].line) 117coccilib.org.print_todo(p1[0], msg) 118 119@as3_prev@ 120expression subE1 <= as3.E1; 121expression subE2 <= as3.E2; 122expression subE3 <= as3.E3; 123expression as3.E1, as3.E2, as3.E3, E4; 124assignment operator aop; 125position p1, p2; 126@@ 127 128* array3_size(E1, E2, E3)@p1 129 ... when != \(subE1\|subE2\|subE3\) aop E4 130 when != &\(subE1\|subE2\|subE3\) 131* E1 * E2 * E3@p2 132 133@script:python depends on report@ 134p1 << as3_prev.p1; 135p2 << as3_prev.p2; 136@@ 137 138msg = "WARNING: array3_size is already used (line %s) to compute the same size" % (p1[0].line) 139coccilib.report.print_report(p2[0], msg) 140 141@script:python depends on org@ 142p1 << as3_prev.p1; 143p2 << as3_prev.p2; 144@@ 145 146msg = "WARNING: array3_size is already used (line %s) to compute the same size" % (p1[0].line) 147coccilib.org.print_todo(p2[0], msg) 148 149@ss@ 150expression E1, E2, E3; 151@@ 152 153struct_size(E1, E2, E3) 154 155@ss_next@ 156expression subE3 <= ss.E3; 157expression ss.E1, ss.E2, ss.E3, E4; 158assignment operator aop; 159position p1, p2; 160@@ 161 162* E1 * E2 + E3@p1 163 ... when != subE3 aop E4 164 when != &subE3 165* struct_size(E1, E2, E3)@p2 166 167@script:python depends on report@ 168p1 << ss_next.p1; 169p2 << ss_next.p2; 170@@ 171 172msg = "WARNING: struct_size is used later (line %s) to compute the same size" % (p2[0].line) 173coccilib.report.print_report(p1[0], msg) 174 175@script:python depends on org@ 176p1 << ss_next.p1; 177p2 << ss_next.p2; 178@@ 179 180msg = "WARNING: struct_size is used later (line %s) to compute the same size" % (p2[0].line) 181coccilib.org.print_todo(p1[0], msg) 182 183@ss_prev@ 184expression subE3 <= ss.E3; 185expression ss.E1, ss.E2, ss.E3, E4; 186assignment operator aop; 187position p1, p2; 188@@ 189 190* struct_size(E1, E2, E3)@p1 191 ... when != subE3 aop E4 192 when != &subE3 193* E1 * E2 + E3@p2 194 195@script:python depends on report@ 196p1 << ss_prev.p1; 197p2 << ss_prev.p2; 198@@ 199 200msg = "WARNING: struct_size is already used (line %s) to compute the same size" % (p1[0].line) 201coccilib.report.print_report(p2[0], msg) 202 203@script:python depends on org@ 204p1 << ss_prev.p1; 205p2 << ss_prev.p2; 206@@ 207 208msg = "WARNING: struct_size is already used (line %s) to compute the same size" % (p1[0].line) 209coccilib.org.print_todo(p2[0], msg) 210