do_div.cocci 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. virtual context
  14. virtual org
  15. virtual report
  16. @initialize:python@
  17. @@
  18. def get_digit_type_and_value(str):
  19. is_digit = False
  20. value = 0
  21. try:
  22. if (str.isdigit()):
  23. is_digit = True
  24. value = int(str, 0)
  25. elif (str.upper().endswith('ULL')):
  26. is_digit = True
  27. value = int(str[:-3], 0)
  28. elif (str.upper().endswith('LL')):
  29. is_digit = True
  30. value = int(str[:-2], 0)
  31. elif (str.upper().endswith('UL')):
  32. is_digit = True
  33. value = int(str[:-2], 0)
  34. elif (str.upper().endswith('L')):
  35. is_digit = True
  36. value = int(str[:-1], 0)
  37. elif (str.upper().endswith('U')):
  38. is_digit = True
  39. value = int(str[:-1], 0)
  40. except Exception as e:
  41. print('Error:',e)
  42. is_digit = False
  43. value = 0
  44. finally:
  45. return is_digit, value
  46. def filter_out_safe_constants(str):
  47. is_digit, value = get_digit_type_and_value(str)
  48. if (is_digit):
  49. if (value >= 0x100000000):
  50. return True
  51. else:
  52. return False
  53. else:
  54. return True
  55. def construct_warnings(suggested_fun):
  56. msg="WARNING: do_div() does a 64-by-32 division, please consider using %s instead."
  57. return msg % suggested_fun
  58. @depends on context@
  59. expression f;
  60. long l: script:python() { filter_out_safe_constants(l) };
  61. unsigned long ul : script:python() { filter_out_safe_constants(ul) };
  62. u64 ul64 : script:python() { filter_out_safe_constants(ul64) };
  63. s64 sl64 : script:python() { filter_out_safe_constants(sl64) };
  64. @@
  65. (
  66. * do_div(f, l);
  67. |
  68. * do_div(f, ul);
  69. |
  70. * do_div(f, ul64);
  71. |
  72. * do_div(f, sl64);
  73. )
  74. @r depends on (org || report)@
  75. expression f;
  76. position p;
  77. long l: script:python() { filter_out_safe_constants(l) };
  78. unsigned long ul : script:python() { filter_out_safe_constants(ul) };
  79. u64 ul64 : script:python() { filter_out_safe_constants(ul64) };
  80. s64 sl64 : script:python() { filter_out_safe_constants(sl64) };
  81. @@
  82. (
  83. do_div@p(f, l);
  84. |
  85. do_div@p(f, ul);
  86. |
  87. do_div@p(f, ul64);
  88. |
  89. do_div@p(f, sl64);
  90. )
  91. @script:python depends on org@
  92. p << r.p;
  93. ul << r.ul;
  94. @@
  95. coccilib.org.print_todo(p[0], construct_warnings("div64_ul"))
  96. @script:python depends on org@
  97. p << r.p;
  98. l << r.l;
  99. @@
  100. coccilib.org.print_todo(p[0], construct_warnings("div64_long"))
  101. @script:python depends on org@
  102. p << r.p;
  103. ul64 << r.ul64;
  104. @@
  105. coccilib.org.print_todo(p[0], construct_warnings("div64_u64"))
  106. @script:python depends on org@
  107. p << r.p;
  108. sl64 << r.sl64;
  109. @@
  110. coccilib.org.print_todo(p[0], construct_warnings("div64_s64"))
  111. @script:python depends on report@
  112. p << r.p;
  113. ul << r.ul;
  114. @@
  115. coccilib.report.print_report(p[0], construct_warnings("div64_ul"))
  116. @script:python depends on report@
  117. p << r.p;
  118. l << r.l;
  119. @@
  120. coccilib.report.print_report(p[0], construct_warnings("div64_long"))
  121. @script:python depends on report@
  122. p << r.p;
  123. sl64 << r.sl64;
  124. @@
  125. coccilib.report.print_report(p[0], construct_warnings("div64_s64"))
  126. @script:python depends on report@
  127. p << r.p;
  128. ul64 << r.ul64;
  129. @@
  130. coccilib.report.print_report(p[0], construct_warnings("div64_u64"))