Skip to content

Commit a746312

Browse files
committed
ICU-23251 Validate serialized spoof data offsets in SpoofData::initPtrs()
Add bounds checking for all offset+size pairs (fCFUKeys, fCFUStringIndex, fCFUStringTable) against the total data length in SpoofData::initPtrs(). Also validate consistency: if confusable keys exist (fCFUKeysSize > 0), the string index and string table must also be present. Without this validation, crafted serialized data passed to uspoof_openFromSerialized() can produce a SpoofChecker with NULL internal pointers, causing a NULL pointer dereference when uspoof_check() is subsequently called.
1 parent 9b16ae8 commit a746312

1 file changed

Lines changed: 34 additions & 0 deletions

File tree

icu4c/source/i18n/uspoof_impl.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,40 @@ void SpoofData::initPtrs(UErrorCode &status) {
687687
if (U_FAILURE(status)) {
688688
return;
689689
}
690+
691+
int32_t totalLen = fRawData->fLength;
692+
if (totalLen < static_cast<int32_t>(sizeof(SpoofDataHeader))) {
693+
status = U_INVALID_FORMAT_ERROR;
694+
return;
695+
}
696+
697+
// Validate all offset+size pairs against the total data length.
698+
if (fRawData->fCFUKeys < 0 || fRawData->fCFUKeys > totalLen ||
699+
fRawData->fCFUKeysSize < 0 ||
700+
fRawData->fCFUKeysSize > (totalLen - fRawData->fCFUKeys) / static_cast<int32_t>(sizeof(int32_t))) {
701+
status = U_INVALID_FORMAT_ERROR;
702+
return;
703+
}
704+
if (fRawData->fCFUStringIndex < 0 || fRawData->fCFUStringIndex > totalLen ||
705+
fRawData->fCFUStringIndexSize < 0 ||
706+
fRawData->fCFUStringIndexSize > (totalLen - fRawData->fCFUStringIndex) / static_cast<int32_t>(sizeof(uint16_t))) {
707+
status = U_INVALID_FORMAT_ERROR;
708+
return;
709+
}
710+
if (fRawData->fCFUStringTable < 0 || fRawData->fCFUStringTable > totalLen ||
711+
fRawData->fCFUStringTableLen < 0 ||
712+
fRawData->fCFUStringTableLen > (totalLen - fRawData->fCFUStringTable) / static_cast<int32_t>(sizeof(char16_t))) {
713+
status = U_INVALID_FORMAT_ERROR;
714+
return;
715+
}
716+
717+
// If keys exist, the value index and string table must also exist.
718+
if (fRawData->fCFUKeysSize > 0 &&
719+
(fRawData->fCFUStringIndex == 0 || fRawData->fCFUStringTable == 0)) {
720+
status = U_INVALID_FORMAT_ERROR;
721+
return;
722+
}
723+
690724
if (fRawData->fCFUKeys != 0) {
691725
fCFUKeys = reinterpret_cast<int32_t*>(reinterpret_cast<char*>(fRawData) + fRawData->fCFUKeys);
692726
}

0 commit comments

Comments
 (0)