ucase_addPropertyStarts(&sa, &status);
break;
case UPROPS_SRC_BIDI:
- ubidi_addPropertyStarts(ubidi_getSingleton(), &sa, &status);
+ ubidi_addPropertyStarts(&sa, &status);
break;
default:
status = U_INTERNAL_PROGRAM_ERROR;
return i.fSet;
}
+namespace {
// Cache some sets for other services -------------------------------------- ***
void U_CALLCONV createUni32Set(UErrorCode &errorCode) {
// memory leak checker tools
#define _dbgct(me)
+} // namespace
+
//----------------------------------------------------------------
// Constructors &c
//----------------------------------------------------------------
// _applyPattern calls add() etc., which set pat to empty.
UnicodeString rebuiltPat;
RuleCharacterIterator chars(pattern, symbols, pos);
- applyPattern(chars, symbols, rebuiltPat, USET_IGNORE_SPACE, NULL, status);
+ applyPattern(chars, symbols, rebuiltPat, USET_IGNORE_SPACE, NULL, 0, status);
if (U_FAILURE(status)) return;
if (chars.inVariable()) {
// syntaxError(chars, "Extra chars in variable value");
// Implementation: Pattern parsing
//----------------------------------------------------------------
+namespace {
+
/**
* A small all-inline class to manage a UnicodeSet pointer. Add
* operator->() etc. as needed.
}
};
+constexpr int32_t MAX_DEPTH = 100;
+
+} // namespace
+
/**
* Parse the pattern from the given RuleCharacterIterator. The
* iterator is advanced over the parsed pattern.
UnicodeString& rebuiltPat,
uint32_t options,
UnicodeSet& (UnicodeSet::*caseClosure)(int32_t attribute),
+ int32_t depth,
UErrorCode& ec) {
if (U_FAILURE(ec)) return;
+ if (depth > MAX_DEPTH) {
+ ec = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
// Syntax characters: [ ] ^ - & { }
}
switch (setMode) {
case 1:
- nested->applyPattern(chars, symbols, patLocal, options, caseClosure, ec);
+ nested->applyPattern(chars, symbols, patLocal, options, caseClosure, depth + 1, ec);
break;
case 2:
chars.skipIgnored(opts);
// Property set implementation
//----------------------------------------------------------------
+namespace {
+
static UBool numericValueFilter(UChar32 ch, void* context) {
return u_getNumericValue(ch) == *(double*)context;
}
return uscript_hasScript(ch, *(UScriptCode*)context);
}
+} // namespace
+
/**
* Generic filter-based scanning code for UCD property UnicodeSets.
*/
}
}
+namespace {
+
static UBool mungeCharName(char* dst, const char* src, int32_t dstCapacity) {
/* Note: we use ' ' in compiler code page */
int32_t j = 0;
return TRUE;
}
+} // namespace
+
//----------------------------------------------------------------
// Property set API
//----------------------------------------------------------------
UProperty p;
int32_t v;
- UBool mustNotBeEmpty = FALSE, invert = FALSE;
+ UBool invert = FALSE;
if (value.length() > 0) {
p = u_getPropertyEnum(pname.data());
p == UCHAR_LEAD_CANONICAL_COMBINING_CLASS) {
char* end;
double value = uprv_strtod(vname.data(), &end);
- v = (int32_t) value;
- if (v != value || v < 0 || *end != 0) {
- // non-integral or negative value, or trailing junk
+ // Anything between 0 and 255 is valid even if unused.
+ // Cast double->int only after range check.
+ // We catch NaN here because comparing it with both 0 and 255 will be false
+ // (as are all comparisons with NaN).
+ if (*end != 0 || !(0 <= value && value <= 255) ||
+ (v = (int32_t)value) != value) {
+ // non-integral value or outside 0..255, or trailing junk
FAIL(ec);
}
- // If the resultant set is empty then the numeric value
- // was invalid.
- mustNotBeEmpty = TRUE;
} else {
FAIL(ec);
}
complement();
}
- if (U_SUCCESS(ec) && (mustNotBeEmpty && isEmpty())) {
- // mustNotBeEmpty is set to true if an empty set indicates
- // invalid input.
- ec = U_ILLEGAL_ARGUMENT_ERROR;
- }
-
if (isBogus() && U_SUCCESS(ec)) {
// We likely ran out of memory. AHHH!
ec = U_MEMORY_ALLOCATION_ERROR;