Skip to content

Commit 3aa85e9

Browse files
committed
ICU-23149 Return error earlier to avoid Null-dereference WRITE
Also add more early error return on the same file to avoid similar mistake.
1 parent 1f33101 commit 3aa85e9

File tree

3 files changed

+21
-0
lines changed

3 files changed

+21
-0
lines changed

icu4c/source/i18n/nfsubs.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ NFSubstitution::makeSubstitution(int32_t pos,
341341
const UnicodeString& description,
342342
UErrorCode& status)
343343
{
344+
if (U_FAILURE(status)) return nullptr;
344345
// if the description is empty, return a NullSubstitution
345346
if (description.length() == 0) {
346347
return nullptr;
@@ -427,6 +428,7 @@ NFSubstitution::NFSubstitution(int32_t _pos,
427428
UErrorCode& status)
428429
: pos(_pos), ruleSet(nullptr), numberFormat(nullptr)
429430
{
431+
if (U_FAILURE(status)) return;
430432
// the description should begin and end with the same character.
431433
// If it doesn't that's a syntax error. Otherwise,
432434
// makeSubstitution() was the only thing that needed to know
@@ -592,6 +594,7 @@ NFSubstitution::toString(UnicodeString& text) const
592594
void
593595
NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const
594596
{
597+
if (U_FAILURE(status)) return;
595598
if (ruleSet != nullptr) {
596599
// Perform a transformation on the number that is dependent
597600
// on the type of substitution this is, then just call its
@@ -634,6 +637,7 @@ NFSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int3
634637
*/
635638
void
636639
NFSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const {
640+
if (U_FAILURE(status)) return;
637641
// perform a transformation on the number being formatted that
638642
// is dependent on the type of substitution this is
639643
double numberToFormat = transformNumber(number);
@@ -850,6 +854,7 @@ ModulusSubstitution::ModulusSubstitution(int32_t _pos,
850854
, divisor(rule->getDivisor())
851855
, ruleToUse(nullptr)
852856
{
857+
if (U_FAILURE(status)) return;
853858
// the owning rule's divisor controls the behavior of this
854859
// substitution: rather than keeping a backpointer to the rule,
855860
// we keep a copy of the divisor
@@ -893,6 +898,7 @@ bool ModulusSubstitution::operator==(const NFSubstitution& rhs) const
893898
void
894899
ModulusSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const
895900
{
901+
if (U_FAILURE(status)) return;
896902
// if this isn't a >>> substitution, just use the inherited version
897903
// of this function (which uses either a rule set or a DecimalFormat
898904
// to format its substitution value)
@@ -918,6 +924,7 @@ ModulusSubstitution::doSubstitution(int64_t number, UnicodeString& toInsertInto,
918924
void
919925
ModulusSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t _pos, int32_t recursionCount, UErrorCode& status) const
920926
{
927+
if (U_FAILURE(status)) return;
921928
// if this isn't a >>> substitution, just use the inherited version
922929
// of this function (which uses either a rule set or a DecimalFormat
923930
// to format its substitution value)
@@ -1026,6 +1033,7 @@ FractionalPartSubstitution::FractionalPartSubstitution(int32_t _pos,
10261033
, useSpaces(true)
10271034

10281035
{
1036+
if (U_FAILURE(status)) return;
10291037
// akk, ruleSet can change in superclass constructor
10301038
if (0 == description.compare(gGreaterGreaterThan, 2) ||
10311039
0 == description.compare(gGreaterGreaterGreaterThan, 3) ||
@@ -1058,6 +1066,7 @@ void
10581066
FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInsertInto,
10591067
int32_t _pos, int32_t recursionCount, UErrorCode& status) const
10601068
{
1069+
if (U_FAILURE(status)) return;
10611070
// if we're not in "byDigits" mode, just use the inherited
10621071
// doSubstitution() routine
10631072
if (!byDigits) {
@@ -1233,6 +1242,7 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(AbsoluteValueSubstitution)
12331242

12341243
void
12351244
NumeratorSubstitution::doSubstitution(double number, UnicodeString& toInsertInto, int32_t apos, int32_t recursionCount, UErrorCode& status) const {
1245+
if (U_FAILURE(status)) return;
12361246
// perform a transformation on the number being formatted that
12371247
// is dependent on the type of substitution this is
12381248

icu4c/source/test/intltest/itrbnf.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ void IntlTestRBNF::runIndexedTest(int32_t index, UBool exec, const char* &name,
8484
TESTCASE(32, TestParseRuleDescriptorOverflow23002);
8585
TESTCASE(33, TestInfiniteRecursion);
8686
TESTCASE(34, testOmissionReplacementWithPluralRules);
87+
TESTCASE(35, TestNullDereferenceWRITE23149);
8788
#else
8889
TESTCASE(0, TestRBNFDisabled);
8990
#endif
@@ -2753,6 +2754,15 @@ IntlTestRBNF::testOmissionReplacementWithPluralRules() {
27532754
doTest(&rbnf, enTestFullData, false);
27542755
}
27552756

2757+
void
2758+
IntlTestRBNF::TestNullDereferenceWRITE23149() {
2759+
UnicodeString test("x00:><>");
2760+
UParseError perror;
2761+
UErrorCode status = U_ZERO_ERROR;
2762+
// The following call should not crash
2763+
icu::RuleBasedNumberFormat rbfmt(test, Locale("en"), perror, status);
2764+
}
2765+
27562766
/* U_HAVE_RBNF */
27572767
#else
27582768

icu4c/source/test/intltest/itrbnf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ class IntlTestRBNF : public IntlTest {
165165
void TestParseRuleDescriptorOverflow23002();
166166
void TestInfiniteRecursion();
167167
void testOmissionReplacementWithPluralRules();
168+
void TestNullDereferenceWRITE23149();
168169

169170
protected:
170171
virtual void doTest(RuleBasedNumberFormat* formatter, const char* const testData[][2], UBool testParsing);

0 commit comments

Comments
 (0)