Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

163 lines
3.5 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. rtloverflow.c
  5. Abstract:
  6. 32bit/64bit signed/unsigned add/multiply with overflow checking
  7. Author:
  8. Jay Krell (JayKrell) January 2002
  9. Revision History:
  10. Environment:
  11. anywhere, only dependency is STATUS_SUCCESS, STATUS_INTEGER_OVERFLOW
  12. Initial client is win32k.sys font loading "rewrite".
  13. --*/
  14. #include "ntos.h"
  15. #include "nt.h"
  16. #include "ntstatus.h"
  17. #include "ntrtloverflow.h"
  18. //
  19. // add functions are FORCEINLINE in ntrtl.h
  20. //
  21. NTSTATUS
  22. RtlpAddWithOverflowCheckUnsigned64(
  23. unsigned __int64 *pc,
  24. unsigned __int64 a,
  25. unsigned __int64 b
  26. )
  27. {
  28. return RtlUnsignedAddWithCarryOut64(pc, a, b) ? STATUS_INTEGER_OVERFLOW : STATUS_SUCCESS;
  29. }
  30. NTSTATUS
  31. NTAPI
  32. RtlMultiplyWithOverflowCheckSigned32(
  33. __int32 * pc,
  34. __int32 a,
  35. __int32 b
  36. )
  37. {
  38. __int64 c;
  39. c = ((__int64)a) * ((__int64)b);
  40. *pc = (__int32)c;
  41. c &= 0xFFFFFFFF80000000ui64;
  42. if ((a < 0) != (b < 0))
  43. {
  44. return (c == 0xFFFFFFFF80000000ui64) ? STATUS_SUCCESS : STATUS_INTEGER_OVERFLOW;
  45. }
  46. else
  47. {
  48. return (c == 0) ? STATUS_SUCCESS : STATUS_INTEGER_OVERFLOW;
  49. }
  50. }
  51. NTSTATUS
  52. NTAPI
  53. RtlMultiplyWithOverflowCheckUnsigned32(
  54. unsigned __int32 * pc,
  55. unsigned __int32 a,
  56. unsigned __int32 b
  57. )
  58. {
  59. unsigned __int64 c;
  60. c = ((unsigned __int64)a) * ((unsigned __int64)b);
  61. *pc = (unsigned __int32)c;
  62. c &= 0xFFFFFFFF00000000ui64;
  63. return (c == 0) ? STATUS_SUCCESS : STATUS_INTEGER_OVERFLOW;
  64. }
  65. NTSTATUS
  66. NTAPI
  67. RtlMultiplyWithOverflowCheckUnsigned64(
  68. unsigned __int64 * pc,
  69. unsigned __int64 a,
  70. unsigned __int64 b
  71. )
  72. {
  73. unsigned __int64 ah;
  74. unsigned __int64 al;
  75. unsigned __int64 bh;
  76. unsigned __int64 bl;
  77. unsigned __int64 c;
  78. unsigned __int64 m;
  79. NTSTATUS Status;
  80. ah = (a >> 32);
  81. bh = (b >> 32);
  82. //
  83. // 09 * 09 = 81 => no overflow
  84. //
  85. if (ah == 0 && bh == 0)
  86. {
  87. *pc = (a * b);
  88. Status = STATUS_SUCCESS;
  89. goto Exit;
  90. }
  91. //
  92. // 10 * 10 = 100 => overflow
  93. //
  94. if (bh != 0 && ah != 0)
  95. {
  96. Status = STATUS_INTEGER_OVERFLOW;
  97. goto Exit;
  98. }
  99. al = (a & 0xFFFFFFFFui64);
  100. bl = (b & 0xFFFFFFFFui64);
  101. //
  102. // a * b = al * bl + (al * bh) * "10" + (ah * bl) * "10" + (ah * bh) * "100"
  103. //
  104. c = (al * bl);
  105. m = (ah * bl);
  106. if ((m & 0xFFFFFFFF00000000ui64) != 0) {
  107. //
  108. // for example: 90 * 09 => overflow
  109. // 09 * 09 => 81, 8 != 0 => overflow
  110. //
  111. // ah != 0 or bh != 0 very often but not always leads to overflow
  112. // 40 * 2 is ok, but 40 * 3 and 50 * 2 are not
  113. //
  114. Status = STATUS_INTEGER_OVERFLOW;
  115. goto Exit;
  116. }
  117. if (!NT_SUCCESS(Status = RtlpAddWithOverflowCheckUnsigned64(&c, c, m << 32))) {
  118. goto Exit;
  119. }
  120. m = (al * bh);
  121. if ((m & 0xFFFFFFFF00000000ui64) != 0) {
  122. //
  123. // for example: 09 * 90 => overflow
  124. // 09 * 09 => 81, 8 != 0 => overflow
  125. //
  126. // ah != 0 or bh != 0 very often but not always leads to overflow
  127. // 40 * 2 is ok, but 40 * 3 and 50 * 2 are not
  128. //
  129. Status = STATUS_INTEGER_OVERFLOW;
  130. goto Exit;
  131. }
  132. if (!NT_SUCCESS(Status = RtlpAddWithOverflowCheckUnsigned64(&c, c, m << 32))) {
  133. goto Exit;
  134. }
  135. *pc = c;
  136. Status = STATUS_SUCCESS;
  137. Exit:
  138. return Status;
  139. }