From cdf52396dcdc6ae3a0002d219c34494aab54c51e Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Mon, 17 Mar 2025 21:41:05 -0700 Subject: [PATCH] ICU-22817 Fix memory leak in basictz by using LocalPointer See https://github.com/LuMingYinDetect/icu_defects/blob/main/icu_1.png --- icu4c/source/i18n/basictz.cpp | 39 ++++++++++++++++------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/icu4c/source/i18n/basictz.cpp b/icu4c/source/i18n/basictz.cpp index 610a31ad5dc..65a9e87a1e9 100644 --- a/icu4c/source/i18n/basictz.cpp +++ b/icu4c/source/i18n/basictz.cpp @@ -140,8 +140,8 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, int32_t initialRaw, initialDst; UnicodeString initialName; - AnnualTimeZoneRule *ar1 = nullptr; - AnnualTimeZoneRule *ar2 = nullptr; + LocalPointer ar1; + LocalPointer ar2; UnicodeString name; UBool avail; @@ -179,8 +179,8 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, // zone to return wrong offset after the transition. // When we encounter such case, we do not inspect next next // transition for another rule. - ar1 = new AnnualTimeZoneRule(name, initialRaw, tr.getTo()->getDSTSavings(), - dtr, year, AnnualTimeZoneRule::MAX_YEAR); + ar1.adoptInstead(new AnnualTimeZoneRule(name, initialRaw, tr.getTo()->getDSTSavings(), + dtr, year, AnnualTimeZoneRule::MAX_YEAR)); if (tr.getTo()->getRawOffset() == initialRaw) { // Get the next next transition @@ -200,8 +200,8 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, // Generate another DOW rule dtr = new DateTimeRule(month, weekInMonth, dow, mid, DateTimeRule::WALL_TIME); tr.getTo()->getName(name); - ar2 = new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(), - dtr, year - 1, AnnualTimeZoneRule::MAX_YEAR); + ar2.adoptInstead(new AnnualTimeZoneRule(name, tr.getTo()->getRawOffset(), tr.getTo()->getDSTSavings(), + dtr, year - 1, AnnualTimeZoneRule::MAX_YEAR)); // Make sure this rule can be applied to the specified date avail = ar2->getPreviousStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), true, d); @@ -209,13 +209,12 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, || initialRaw != tr.getTo()->getRawOffset() || initialDst != tr.getTo()->getDSTSavings()) { // We cannot use this rule as the second transition rule - delete ar2; - ar2 = nullptr; + ar2.adoptInstead(nullptr); } } } } - if (ar2 == nullptr) { + if (ar2.isNull()) { // Try previous transition avail = getPreviousTransition(date, true, tr); if (avail) { @@ -234,23 +233,21 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, // second rule raw/dst offsets should match raw/dst offsets // at the given time - ar2 = new AnnualTimeZoneRule(name, initialRaw, initialDst, - dtr, ar1->getStartYear() - 1, AnnualTimeZoneRule::MAX_YEAR); + ar2.adoptInstead(new AnnualTimeZoneRule(name, initialRaw, initialDst, + dtr, ar1->getStartYear() - 1, AnnualTimeZoneRule::MAX_YEAR)); // Check if this rule start after the first rule after the specified date avail = ar2->getNextStart(date, tr.getFrom()->getRawOffset(), tr.getFrom()->getDSTSavings(), false, d); if (!avail || d <= nextTransitionTime) { // We cannot use this rule as the second transition rule - delete ar2; - ar2 = nullptr; + ar2.adoptInstead(nullptr); } } } } - if (ar2 == nullptr) { + if (ar2.isNull()) { // Cannot find a good pair of AnnualTimeZoneRule - delete ar1; - ar1 = nullptr; + ar1.adoptInstead(nullptr); } else { // The initial rule should represent the rule before the previous transition ar1->getName(initialName); @@ -278,13 +275,13 @@ BasicTimeZone::getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, initial = new InitialTimeZoneRule(initialName, initialRaw, initialDst); // Set the standard and daylight saving rules - if (ar1 != nullptr && ar2 != nullptr) { + if (ar1.isValid() && ar2.isValid()) { if (ar1->getDSTSavings() != 0) { - dst = ar1; - std = ar2; + dst = ar1.orphan(); + std = ar2.orphan(); } else { - std = ar1; - dst = ar2; + std = ar1.orphan(); + dst = ar2.orphan(); } } }