0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /// do_div() does a 64-by-32 division.
0003 /// When the divisor is long, unsigned long, u64, or s64,
0004 /// do_div() truncates it to 32 bits, this means it can test
0005 /// non-zero and be truncated to 0 for division on 64bit platforms.
0006 ///
0007 //# This makes an effort to find those inappropriate do_div() calls.
0008 //
0009 // Confidence: Moderate
0010 // Copyright: (C) 2020 Wen Yang, Alibaba.
0011 // Comments:
0012 // Options: --no-includes --include-headers
0013
0014 virtual context
0015 virtual org
0016 virtual report
0017
0018 @initialize:python@
0019 @@
0020
0021 def get_digit_type_and_value(str):
0022 is_digit = False
0023 value = 0
0024
0025 try:
0026 if (str.isdigit()):
0027 is_digit = True
0028 value = int(str, 0)
0029 elif (str.upper().endswith('ULL')):
0030 is_digit = True
0031 value = int(str[:-3], 0)
0032 elif (str.upper().endswith('LL')):
0033 is_digit = True
0034 value = int(str[:-2], 0)
0035 elif (str.upper().endswith('UL')):
0036 is_digit = True
0037 value = int(str[:-2], 0)
0038 elif (str.upper().endswith('L')):
0039 is_digit = True
0040 value = int(str[:-1], 0)
0041 elif (str.upper().endswith('U')):
0042 is_digit = True
0043 value = int(str[:-1], 0)
0044 except Exception as e:
0045 print('Error:',e)
0046 is_digit = False
0047 value = 0
0048 finally:
0049 return is_digit, value
0050
0051 def filter_out_safe_constants(str):
0052 is_digit, value = get_digit_type_and_value(str)
0053 if (is_digit):
0054 if (value >= 0x100000000):
0055 return True
0056 else:
0057 return False
0058 else:
0059 return True
0060
0061 def construct_warnings(suggested_fun):
0062 msg="WARNING: do_div() does a 64-by-32 division, please consider using %s instead."
0063 return msg % suggested_fun
0064
0065 @depends on context@
0066 expression f;
0067 long l: script:python() { filter_out_safe_constants(l) };
0068 unsigned long ul : script:python() { filter_out_safe_constants(ul) };
0069 u64 ul64 : script:python() { filter_out_safe_constants(ul64) };
0070 s64 sl64 : script:python() { filter_out_safe_constants(sl64) };
0071
0072 @@
0073 (
0074 * do_div(f, l);
0075 |
0076 * do_div(f, ul);
0077 |
0078 * do_div(f, ul64);
0079 |
0080 * do_div(f, sl64);
0081 )
0082
0083 @r depends on (org || report)@
0084 expression f;
0085 position p;
0086 long l: script:python() { filter_out_safe_constants(l) };
0087 unsigned long ul : script:python() { filter_out_safe_constants(ul) };
0088 u64 ul64 : script:python() { filter_out_safe_constants(ul64) };
0089 s64 sl64 : script:python() { filter_out_safe_constants(sl64) };
0090 @@
0091 (
0092 do_div@p(f, l);
0093 |
0094 do_div@p(f, ul);
0095 |
0096 do_div@p(f, ul64);
0097 |
0098 do_div@p(f, sl64);
0099 )
0100
0101 @script:python depends on org@
0102 p << r.p;
0103 ul << r.ul;
0104 @@
0105
0106 coccilib.org.print_todo(p[0], construct_warnings("div64_ul"))
0107
0108 @script:python depends on org@
0109 p << r.p;
0110 l << r.l;
0111 @@
0112
0113 coccilib.org.print_todo(p[0], construct_warnings("div64_long"))
0114
0115 @script:python depends on org@
0116 p << r.p;
0117 ul64 << r.ul64;
0118 @@
0119
0120 coccilib.org.print_todo(p[0], construct_warnings("div64_u64"))
0121
0122 @script:python depends on org@
0123 p << r.p;
0124 sl64 << r.sl64;
0125 @@
0126
0127 coccilib.org.print_todo(p[0], construct_warnings("div64_s64"))
0128
0129 @script:python depends on report@
0130 p << r.p;
0131 ul << r.ul;
0132 @@
0133
0134 coccilib.report.print_report(p[0], construct_warnings("div64_ul"))
0135
0136 @script:python depends on report@
0137 p << r.p;
0138 l << r.l;
0139 @@
0140
0141 coccilib.report.print_report(p[0], construct_warnings("div64_long"))
0142
0143 @script:python depends on report@
0144 p << r.p;
0145 sl64 << r.sl64;
0146 @@
0147
0148 coccilib.report.print_report(p[0], construct_warnings("div64_s64"))
0149
0150 @script:python depends on report@
0151 p << r.p;
0152 ul64 << r.ul64;
0153 @@
0154
0155 coccilib.report.print_report(p[0], construct_warnings("div64_u64"))