CVE-2017-15422.patch 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. Backport of <https://github.com/unicode-org/icu/commit/b7d08bc04>
  2. ~~~
  3. From 71dd84d4ffd6600a70e5bca56a22b957e6642bd4 Mon Sep 17 00:00:00 2001
  4. From: Peter Edberg <pedberg@unicode.org>
  5. Date: Sun, 29 Oct 2017 03:38:05 +0000
  6. Subject: [PATCH] ICU-12504 in ICU4C Persian cal, use int64_t math for one
  7. operation to avoid overflow; add tests in C and J
  8. X-SVN-Rev: 40654
  9. ---
  10. icu4c/source/i18n/gregoimp.cpp | 5 +++
  11. icu4c/source/i18n/gregoimp.h | 11 ++++++
  12. icu4c/source/i18n/persncal.cpp | 2 +-
  13. icu4c/source/test/intltest/calregts.cpp | 34 ++++++++++++++++++-
  14. icu4c/source/test/intltest/calregts.h | 1 +
  15. .../test/calendar/CalendarRegressionTest.java | 20 ++++++++++-
  16. 6 files changed, 70 insertions(+), 3 deletions(-)
  17. ~~~
  18. --- source/i18n/gregoimp.cpp
  19. +++ source/i18n/gregoimp.cpp
  20. @@ -27,6 +27,11 @@ int32_t ClockMath::floorDivide(int32_t numerator, int32_t denominator) {
  21. numerator / denominator : ((numerator + 1) / denominator) - 1;
  22. }
  23. +int64_t ClockMath::floorDivide(int64_t numerator, int64_t denominator) {
  24. + return (numerator >= 0) ?
  25. + numerator / denominator : ((numerator + 1) / denominator) - 1;
  26. +}
  27. +
  28. int32_t ClockMath::floorDivide(double numerator, int32_t denominator,
  29. int32_t& remainder) {
  30. double quotient;
  31. --- source/i18n/gregoimp.h
  32. +++ source/i18n/gregoimp.h
  33. @@ -40,6 +40,17 @@ class ClockMath {
  34. */
  35. static int32_t floorDivide(int32_t numerator, int32_t denominator);
  36. + /**
  37. + * Divide two integers, returning the floor of the quotient.
  38. + * Unlike the built-in division, this is mathematically
  39. + * well-behaved. E.g., <code>-1/4</code> => 0 but
  40. + * <code>floorDivide(-1,4)</code> => -1.
  41. + * @param numerator the numerator
  42. + * @param denominator a divisor which must be != 0
  43. + * @return the floor of the quotient
  44. + */
  45. + static int64_t floorDivide(int64_t numerator, int64_t denominator);
  46. +
  47. /**
  48. * Divide two numbers, returning the floor of the quotient.
  49. * Unlike the built-in division, this is mathematically
  50. --- source/i18n/persncal.cpp
  51. +++ source/i18n/persncal.cpp
  52. @@ -213,7 +213,7 @@ void PersianCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*statu
  53. int32_t year, month, dayOfMonth, dayOfYear;
  54. int32_t daysSinceEpoch = julianDay - PERSIAN_EPOCH;
  55. - year = 1 + ClockMath::floorDivide(33 * daysSinceEpoch + 3, 12053);
  56. + year = 1 + (int32_t)ClockMath::floorDivide(33 * (int64_t)daysSinceEpoch + 3, (int64_t)12053);
  57. int32_t farvardin1 = 365 * (year - 1) + ClockMath::floorDivide(8 * year + 21, 33);
  58. dayOfYear = (daysSinceEpoch - farvardin1); // 0-based
  59. --- source/test/intltest/calregts.cpp
  60. +++ source/test/intltest/calregts.cpp
  61. @@ -12,6 +12,7 @@
  62. #include "calregts.h"
  63. +#include "unicode/calendar.h"
  64. #include "unicode/gregocal.h"
  65. #include "unicode/simpletz.h"
  66. #include "unicode/smpdtfmt.h"
  67. @@ -90,6 +91,7 @@ CalendarRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &
  68. CASE(48,TestT8596);
  69. CASE(49,Test9019);
  70. CASE(50,TestT9452);
  71. + CASE(52,TestPersianCalOverflow);
  72. default: name = ""; break;
  73. }
  74. }
  75. @@ -2946,4 +2948,34 @@ void CalendarRegressionTest::TestT9452(void) {
  76. }
  77. }
  78. +/**
  79. + * @bug ticket 13454
  80. + */
  81. +void CalendarRegressionTest::TestPersianCalOverflow(void) {
  82. + const char* localeID = "bs_Cyrl@calendar=persian";
  83. + UErrorCode status = U_ZERO_ERROR;
  84. + Calendar* cal = Calendar::createInstance(Locale(localeID), status);
  85. + if(U_FAILURE(status)) {
  86. + dataerrln("FAIL: Calendar::createInstance for localeID %s: %s", localeID, u_errorName(status));
  87. + } else {
  88. + int32_t maxMonth = cal->getMaximum(UCAL_MONTH);
  89. + int32_t maxDayOfMonth = cal->getMaximum(UCAL_DATE);
  90. + int32_t jd, month, dayOfMonth;
  91. + for (jd = 67023580; jd <= 67023584; jd++) { // year 178171, int32_t overflow if jd >= 67023582
  92. + status = U_ZERO_ERROR;
  93. + cal->clear();
  94. + cal->set(UCAL_JULIAN_DAY, jd);
  95. + month = cal->get(UCAL_MONTH, status);
  96. + dayOfMonth = cal->get(UCAL_DATE, status);
  97. + if ( U_FAILURE(status) ) {
  98. + errln("FAIL: Calendar->get MONTH/DATE for localeID %s, julianDay %d, status %s\n", localeID, jd, u_errorName(status));
  99. + } else if (month > maxMonth || dayOfMonth > maxDayOfMonth) {
  100. + errln("FAIL: localeID %s, julianDay %d; maxMonth %d, got month %d; maxDayOfMonth %d, got dayOfMonth %d\n",
  101. + localeID, jd, maxMonth, month, maxDayOfMonth, dayOfMonth);
  102. + }
  103. + }
  104. + delete cal;
  105. + }
  106. +}
  107. +
  108. #endif /* #if !UCONFIG_NO_FORMATTING */
  109. --- source/test/intltest/calregts.h
  110. +++ source/test/intltest/calregts.h
  111. @@ -77,6 +77,7 @@ public:
  112. void TestT8596(void);
  113. void Test9019(void);
  114. void TestT9452(void);
  115. + void TestPersianCalOverflow(void);
  116. void printdate(GregorianCalendar *cal, const char *string);
  117. void dowTest(UBool lenient) ;