| // SPDX-License-Identifier: GPL-2.0-only | |
| /// do_div() does a 64-by-32 division. | |
| /// When the divisor is long, unsigned long, u64, or s64, | |
| /// do_div() truncates it to 32 bits, this means it can test | |
| /// non-zero and be truncated to 0 for division on 64bit platforms. | |
| /// | |
| //# This makes an effort to find those inappropriate do_div() calls. | |
| // | |
| // Confidence: Moderate | |
| // Copyright: (C) 2020 Wen Yang, Alibaba. | |
| // Comments: | |
| // Options: --no-includes --include-headers | |
| virtual context | |
| virtual org | |
| virtual report | |
| @initialize:python@ | |
| @@ | |
| def get_digit_type_and_value(str): | |
| is_digit = False | |
| value = 0 | |
| try: | |
| if (str.isdigit()): | |
| is_digit = True | |
| value = int(str, 0) | |
| elif (str.upper().endswith('ULL')): | |
| is_digit = True | |
| value = int(str[:-3], 0) | |
| elif (str.upper().endswith('LL')): | |
| is_digit = True | |
| value = int(str[:-2], 0) | |
| elif (str.upper().endswith('UL')): | |
| is_digit = True | |
| value = int(str[:-2], 0) | |
| elif (str.upper().endswith('L')): | |
| is_digit = True | |
| value = int(str[:-1], 0) | |
| elif (str.upper().endswith('U')): | |
| is_digit = True | |
| value = int(str[:-1], 0) | |
| except Exception as e: | |
| print('Error:',e) | |
| is_digit = False | |
| value = 0 | |
| finally: | |
| return is_digit, value | |
| def filter_out_safe_constants(str): | |
| is_digit, value = get_digit_type_and_value(str) | |
| if (is_digit): | |
| if (value >= 0x100000000): | |
| return True | |
| else: | |
| return False | |
| else: | |
| return True | |
| def construct_warnings(suggested_fun): | |
| msg="WARNING: do_div() does a 64-by-32 division, please consider using %s instead." | |
| return msg % suggested_fun | |
| @depends on context@ | |
| expression f; | |
| long l: script:python() { filter_out_safe_constants(l) }; | |
| unsigned long ul : script:python() { filter_out_safe_constants(ul) }; | |
| u64 ul64 : script:python() { filter_out_safe_constants(ul64) }; | |
| s64 sl64 : script:python() { filter_out_safe_constants(sl64) }; | |
| @@ | |
| ( | |
| * do_div(f, l); | |
| | | |
| * do_div(f, ul); | |
| | | |
| * do_div(f, ul64); | |
| | | |
| * do_div(f, sl64); | |
| ) | |
| @r depends on (org || report)@ | |
| expression f; | |
| position p; | |
| long l: script:python() { filter_out_safe_constants(l) }; | |
| unsigned long ul : script:python() { filter_out_safe_constants(ul) }; | |
| u64 ul64 : script:python() { filter_out_safe_constants(ul64) }; | |
| s64 sl64 : script:python() { filter_out_safe_constants(sl64) }; | |
| @@ | |
| ( | |
| do_div@p(f, l); | |
| | | |
| do_div@p(f, ul); | |
| | | |
| do_div@p(f, ul64); | |
| | | |
| do_div@p(f, sl64); | |
| ) | |
| @script:python depends on org@ | |
| p << r.p; | |
| ul << r.ul; | |
| @@ | |
| coccilib.org.print_todo(p[0], construct_warnings("div64_ul")) | |
| @script:python depends on org@ | |
| p << r.p; | |
| l << r.l; | |
| @@ | |
| coccilib.org.print_todo(p[0], construct_warnings("div64_long")) | |
| @script:python depends on org@ | |
| p << r.p; | |
| ul64 << r.ul64; | |
| @@ | |
| coccilib.org.print_todo(p[0], construct_warnings("div64_u64")) | |
| @script:python depends on org@ | |
| p << r.p; | |
| sl64 << r.sl64; | |
| @@ | |
| coccilib.org.print_todo(p[0], construct_warnings("div64_s64")) | |
| @script:python depends on report@ | |
| p << r.p; | |
| ul << r.ul; | |
| @@ | |
| coccilib.report.print_report(p[0], construct_warnings("div64_ul")) | |
| @script:python depends on report@ | |
| p << r.p; | |
| l << r.l; | |
| @@ | |
| coccilib.report.print_report(p[0], construct_warnings("div64_long")) | |
| @script:python depends on report@ | |
| p << r.p; | |
| sl64 << r.sl64; | |
| @@ | |
| coccilib.report.print_report(p[0], construct_warnings("div64_s64")) | |
| @script:python depends on report@ | |
| p << r.p; | |
| ul64 << r.ul64; | |
| @@ | |
| coccilib.report.print_report(p[0], construct_warnings("div64_u64")) |