1// SPDX-License-Identifier: GPL-2.0-only 2/// do_div() does a 64-by-32 division. 3/// When the divisor is long, unsigned long, u64, or s64, 4/// do_div() truncates it to 32 bits, this means it can test 5/// non-zero and be truncated to 0 for division on 64bit platforms. 6/// 7//# This makes an effort to find those inappropriate do_div() calls. 8// 9// Confidence: Moderate 10// Copyright: (C) 2020 Wen Yang, Alibaba. 11// Comments: 12// Options: --no-includes --include-headers 13 14virtual context 15virtual org 16virtual report 17 18@initialize:python@ 19@@ 20 21def get_digit_type_and_value(str): 22 is_digit = False 23 value = 0 24 25 try: 26 if (str.isdigit()): 27 is_digit = True 28 value = int(str, 0) 29 elif (str.upper().endswith('ULL')): 30 is_digit = True 31 value = int(str[:-3], 0) 32 elif (str.upper().endswith('LL')): 33 is_digit = True 34 value = int(str[:-2], 0) 35 elif (str.upper().endswith('UL')): 36 is_digit = True 37 value = int(str[:-2], 0) 38 elif (str.upper().endswith('L')): 39 is_digit = True 40 value = int(str[:-1], 0) 41 elif (str.upper().endswith('U')): 42 is_digit = True 43 value = int(str[:-1], 0) 44 except Exception as e: 45 print('Error:',e) 46 is_digit = False 47 value = 0 48 finally: 49 return is_digit, value 50 51def filter_out_safe_constants(str): 52 is_digit, value = get_digit_type_and_value(str) 53 if (is_digit): 54 if (value >= 0x100000000): 55 return True 56 else: 57 return False 58 else: 59 return True 60 61def construct_warnings(suggested_fun): 62 msg="WARNING: do_div() does a 64-by-32 division, please consider using %s instead." 63 return msg % suggested_fun 64 65@depends on context@ 66expression f; 67long l: script:python() { filter_out_safe_constants(l) }; 68unsigned long ul : script:python() { filter_out_safe_constants(ul) }; 69u64 ul64 : script:python() { filter_out_safe_constants(ul64) }; 70s64 sl64 : script:python() { filter_out_safe_constants(sl64) }; 71 72@@ 73( 74* do_div(f, l); 75| 76* do_div(f, ul); 77| 78* do_div(f, ul64); 79| 80* do_div(f, sl64); 81) 82 83@r depends on (org || report)@ 84expression f; 85position p; 86long l: script:python() { filter_out_safe_constants(l) }; 87unsigned long ul : script:python() { filter_out_safe_constants(ul) }; 88u64 ul64 : script:python() { filter_out_safe_constants(ul64) }; 89s64 sl64 : script:python() { filter_out_safe_constants(sl64) }; 90@@ 91( 92do_div@p(f, l); 93| 94do_div@p(f, ul); 95| 96do_div@p(f, ul64); 97| 98do_div@p(f, sl64); 99) 100 101@script:python depends on org@ 102p << r.p; 103ul << r.ul; 104@@ 105 106coccilib.org.print_todo(p[0], construct_warnings("div64_ul")) 107 108@script:python depends on org@ 109p << r.p; 110l << r.l; 111@@ 112 113coccilib.org.print_todo(p[0], construct_warnings("div64_long")) 114 115@script:python depends on org@ 116p << r.p; 117ul64 << r.ul64; 118@@ 119 120coccilib.org.print_todo(p[0], construct_warnings("div64_u64")) 121 122@script:python depends on org@ 123p << r.p; 124sl64 << r.sl64; 125@@ 126 127coccilib.org.print_todo(p[0], construct_warnings("div64_s64")) 128 129@script:python depends on report@ 130p << r.p; 131ul << r.ul; 132@@ 133 134coccilib.report.print_report(p[0], construct_warnings("div64_ul")) 135 136@script:python depends on report@ 137p << r.p; 138l << r.l; 139@@ 140 141coccilib.report.print_report(p[0], construct_warnings("div64_long")) 142 143@script:python depends on report@ 144p << r.p; 145sl64 << r.sl64; 146@@ 147 148coccilib.report.print_report(p[0], construct_warnings("div64_s64")) 149 150@script:python depends on report@ 151p << r.p; 152ul64 << r.ul64; 153@@ 154 155coccilib.report.print_report(p[0], construct_warnings("div64_u64")) 156