}
void SpoofImpl::construct(UErrorCode& status) {
- fMagic = USPOOF_MAGIC;
fChecks = USPOOF_ALL_CHECKS;
fSpoofData = NULL;
fAllowedCharsSet = NULL;
// Copy Constructor, used by the user level clone() function.
SpoofImpl::SpoofImpl(const SpoofImpl &src, UErrorCode &status) :
- fMagic(0), fChecks(USPOOF_ALL_CHECKS), fSpoofData(NULL), fAllowedCharsSet(NULL) ,
+ fChecks(USPOOF_ALL_CHECKS), fSpoofData(NULL), fAllowedCharsSet(NULL) ,
fAllowedLocales(NULL) {
if (U_FAILURE(status)) {
return;
}
- fMagic = src.fMagic;
fChecks = src.fChecks;
if (src.fSpoofData != NULL) {
fSpoofData = src.fSpoofData->addReference();
}
- fAllowedCharsSet = static_cast<const UnicodeSet *>(src.fAllowedCharsSet->clone());
+ fAllowedCharsSet = src.fAllowedCharsSet->clone();
fAllowedLocales = uprv_strdup(src.fAllowedLocales);
if (fAllowedCharsSet == NULL || fAllowedLocales == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
SpoofImpl::~SpoofImpl() {
- fMagic = 0; // head off application errors by preventing use of
- // of deleted objects.
if (fSpoofData != NULL) {
fSpoofData->removeReference(); // Will delete if refCount goes to zero.
}
// Cast this instance as a USpoofChecker for the C API.
USpoofChecker *SpoofImpl::asUSpoofChecker() {
- return reinterpret_cast<USpoofChecker*>(this);
+ return exportForC();
}
//
// received from the C API.
//
const SpoofImpl *SpoofImpl::validateThis(const USpoofChecker *sc, UErrorCode &status) {
+ auto* This = validate(sc, status);
if (U_FAILURE(status)) {
return NULL;
}
- if (sc == NULL) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return NULL;
- }
- SpoofImpl *This = (SpoofImpl *)sc;
- if (This->fMagic != USPOOF_MAGIC) {
- status = U_INVALID_FORMAT_ERROR;
- return NULL;
- }
if (This->fSpoofData != NULL && !This->fSpoofData->validateDataVersion(status)) {
return NULL;
}
}
// Store the updated spoof checker state.
- tmpSet = static_cast<UnicodeSet *>(allowedChars.clone());
+ tmpSet = allowedChars.clone();
const char *tmpLocalesList = uprv_strdup(localesList);
if (tmpSet == NULL || tmpLocalesList == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return USPOOF_MINIMALLY_RESTRICTIVE;
}
+int32_t SpoofImpl::findHiddenOverlay(const UnicodeString& input, UErrorCode&) const {
+ bool sawLeadCharacter = false;
+ for (int32_t i=0; i<input.length();) {
+ UChar32 cp = input.char32At(i);
+ if (sawLeadCharacter && cp == 0x0307) {
+ return i;
+ }
+ uint8_t combiningClass = u_getCombiningClass(cp);
+ // Skip over characters except for those with combining class 0 (non-combining characters) or with
+ // combining class 230 (same class as U+0307)
+ U_ASSERT(u_getCombiningClass(0x0307) == 230);
+ if (combiningClass == 0 || combiningClass == 230) {
+ sawLeadCharacter = isIllegalCombiningDotLeadCharacter(cp);
+ }
+ i += U16_LENGTH(cp);
+ }
+ return -1;
+}
+
+static inline bool isIllegalCombiningDotLeadCharacterNoLookup(UChar32 cp) {
+ return cp == u'i' || cp == u'j' || cp == u'ı' || cp == u'ȷ' || cp == u'l' ||
+ u_hasBinaryProperty(cp, UCHAR_SOFT_DOTTED);
+}
+
+bool SpoofImpl::isIllegalCombiningDotLeadCharacter(UChar32 cp) const {
+ if (isIllegalCombiningDotLeadCharacterNoLookup(cp)) {
+ return true;
+ }
+ UnicodeString skelStr;
+ fSpoofData->confusableLookup(cp, skelStr);
+ UChar32 finalCp = skelStr.char32At(skelStr.moveIndex32(skelStr.length(), -1));
+ if (finalCp != cp && isIllegalCombiningDotLeadCharacterNoLookup(finalCp)) {
+ return true;
+ }
+ return false;
+}
+
// Convert a text format hex number. Utility function used by builder code. Static.
//
//-----------------------------------------
-CheckResult::CheckResult() : fMagic(USPOOF_CHECK_MAGIC) {
+CheckResult::CheckResult() {
clear();
}
USpoofCheckResult* CheckResult::asUSpoofCheckResult() {
- return reinterpret_cast<USpoofCheckResult*>(this);
+ return exportForC();
}
//
// received from the C API.
//
const CheckResult* CheckResult::validateThis(const USpoofCheckResult *ptr, UErrorCode &status) {
- if (U_FAILURE(status)) { return NULL; }
- if (ptr == NULL) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return NULL;
- }
- CheckResult *This = (CheckResult*) ptr;
- if (This->fMagic != USPOOF_CHECK_MAGIC) {
- status = U_INVALID_FORMAT_ERROR;
- return NULL;
- }
- return This;
+ return validate(ptr, status);
}
CheckResult* CheckResult::validateThis(USpoofCheckResult *ptr, UErrorCode &status) {
- return const_cast<CheckResult *>
- (CheckResult::validateThis(const_cast<const USpoofCheckResult*>(ptr), status));
+ return validate(ptr, status);
}
void CheckResult::clear() {
if (gDefaultSpoofData) {
// Will delete, assuming all user-level spoof checkers were closed.
gDefaultSpoofData->removeReference();
- gDefaultSpoofData = NULL;
+ gDefaultSpoofData = nullptr;
gSpoofInitDefaultOnce.reset();
}
return TRUE;
}
static void U_CALLCONV uspoof_loadDefaultData(UErrorCode& status) {
- UDataMemory *udm = udata_openChoice(NULL, "cfu", "confusables",
+ UDataMemory *udm = udata_openChoice(nullptr, "cfu", "confusables",
spoofDataIsAcceptable,
- NULL, // context, would receive dataVersion if supplied.
+ nullptr, // context, would receive dataVersion if supplied.
&status);
if (U_FAILURE(status)) { return; }
gDefaultSpoofData = new SpoofData(udm, status);
if (U_FAILURE(status)) {
delete gDefaultSpoofData;
+ gDefaultSpoofData = nullptr;
return;
}
- if (gDefaultSpoofData == NULL) {
+ if (gDefaultSpoofData == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
status = U_INVALID_FORMAT_ERROR;
return;
}
+ if (data == NULL) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
void *ncData = const_cast<void *>(data);
fRawData = static_cast<SpoofDataHeader *>(ncData);
if (length < fRawData->fLength) {
return NULL;
}
if (!fDataOwned) {
- U_ASSERT(FALSE);
- status = U_INTERNAL_PROGRAM_ERROR;
- return NULL;
+ UPRV_UNREACHABLE;
}
numBytes = (numBytes + 15) & ~15; // Round up to a multiple of 16