mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-17 02:37:25 +00:00
ICU-13380 Fixing memory overflow in MeasureFormat data loading.
X-SVN-Rev: 40516
This commit is contained in:
parent
b06ac0cc8f
commit
9fbda43d48
1 changed files with 22 additions and 21 deletions
|
@ -42,11 +42,14 @@
|
|||
#include "standardplural.h"
|
||||
#include "unifiedcache.h"
|
||||
|
||||
#define MEAS_UNIT_COUNT 135
|
||||
#define WIDTH_INDEX_COUNT (UMEASFMT_WIDTH_NARROW + 1)
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
static constexpr int32_t PER_UNIT_INDEX = StandardPlural::COUNT;
|
||||
static constexpr int32_t PATTERN_COUNT = PER_UNIT_INDEX + 1;
|
||||
static constexpr int32_t MEAS_UNIT_COUNT = 138; // see assertion in MeasureFormatCacheData constructor
|
||||
static constexpr int32_t WIDTH_INDEX_COUNT = UMEASFMT_WIDTH_NARROW + 1;
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat)
|
||||
|
||||
// Used to format durations like 5:47 or 21:35:42.
|
||||
|
@ -100,8 +103,6 @@ static UMeasureFormatWidth getRegularWidth(UMeasureFormatWidth width) {
|
|||
*/
|
||||
class MeasureFormatCacheData : public SharedObject {
|
||||
public:
|
||||
static const int32_t PER_UNIT_INDEX = StandardPlural::COUNT;
|
||||
static const int32_t PATTERN_COUNT = PER_UNIT_INDEX + 1;
|
||||
|
||||
/**
|
||||
* Redirection data from root-bundle, top-level sideways aliases.
|
||||
|
@ -110,8 +111,8 @@ public:
|
|||
*/
|
||||
UMeasureFormatWidth widthFallback[WIDTH_INDEX_COUNT];
|
||||
/** Measure unit -> format width -> array of patterns ("{0} meters") (plurals + PER_UNIT_INDEX) */
|
||||
SimpleFormatter *patterns[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT][PATTERN_COUNT];
|
||||
const UChar* dnams[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT];
|
||||
SimpleFormatter* patterns[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT][PATTERN_COUNT] = {};
|
||||
const UChar* dnams[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT] = {};
|
||||
SimpleFormatter perFormatters[WIDTH_INDEX_COUNT];
|
||||
|
||||
MeasureFormatCacheData();
|
||||
|
@ -146,24 +147,21 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
NumberFormat *currencyFormats[WIDTH_INDEX_COUNT];
|
||||
NumberFormat *integerFormat;
|
||||
NumericDateFormatters *numericDateFormatters;
|
||||
NumberFormat* currencyFormats[WIDTH_INDEX_COUNT] = {};
|
||||
NumberFormat* integerFormat = nullptr;
|
||||
NumericDateFormatters* numericDateFormatters = nullptr;
|
||||
|
||||
MeasureFormatCacheData(const MeasureFormatCacheData &other);
|
||||
MeasureFormatCacheData &operator=(const MeasureFormatCacheData &other);
|
||||
};
|
||||
|
||||
MeasureFormatCacheData::MeasureFormatCacheData() {
|
||||
// Please update MEAS_UNIT_COUNT if it gets out of sync with the true count!
|
||||
U_ASSERT(MEAS_UNIT_COUNT == MeasureUnit::getIndexCount());
|
||||
|
||||
for (int32_t i = 0; i < WIDTH_INDEX_COUNT; ++i) {
|
||||
widthFallback[i] = UMEASFMT_WIDTH_COUNT;
|
||||
}
|
||||
for (int32_t i = 0; i < UPRV_LENGTHOF(currencyFormats); ++i) {
|
||||
currencyFormats[i] = NULL;
|
||||
}
|
||||
uprv_memset(patterns, 0, sizeof(patterns));
|
||||
uprv_memset(dnams, 0, sizeof(dnams));
|
||||
integerFormat = NULL;
|
||||
numericDateFormatters = NULL;
|
||||
}
|
||||
|
||||
MeasureFormatCacheData::~MeasureFormatCacheData() {
|
||||
|
@ -236,6 +234,9 @@ struct UnitDataSink : public ResourceSink {
|
|||
|
||||
void setFormatterIfAbsent(int32_t index, const ResourceValue &value,
|
||||
int32_t minPlaceholders, UErrorCode &errorCode) {
|
||||
U_ASSERT(unitIndex < MEAS_UNIT_COUNT);
|
||||
U_ASSERT(width < WIDTH_INDEX_COUNT);
|
||||
U_ASSERT(index < PATTERN_COUNT);
|
||||
SimpleFormatter **patterns = &cacheData.patterns[unitIndex][width][0];
|
||||
if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
|
||||
if (minPlaceholders >= 0) {
|
||||
|
@ -249,6 +250,8 @@ struct UnitDataSink : public ResourceSink {
|
|||
}
|
||||
|
||||
void setDnamIfAbsent(const ResourceValue &value, UErrorCode& errorCode) {
|
||||
U_ASSERT(unitIndex < MEAS_UNIT_COUNT);
|
||||
U_ASSERT(width < WIDTH_INDEX_COUNT);
|
||||
if (cacheData.dnams[unitIndex][width] == NULL) {
|
||||
int32_t length;
|
||||
cacheData.dnams[unitIndex][width] = value.getString(length, errorCode);
|
||||
|
@ -266,7 +269,7 @@ struct UnitDataSink : public ResourceSink {
|
|||
setDnamIfAbsent(value, errorCode);
|
||||
} else if (uprv_strcmp(key, "per") == 0) {
|
||||
// For example, "{0}/h".
|
||||
setFormatterIfAbsent(MeasureFormatCacheData::PER_UNIT_INDEX, value, 1, errorCode);
|
||||
setFormatterIfAbsent(PER_UNIT_INDEX, value, 1, errorCode);
|
||||
} else {
|
||||
// The key must be one of the plural form strings. For example:
|
||||
// one{"{0} hr"}
|
||||
|
@ -1093,8 +1096,7 @@ UnicodeString &MeasureFormat::formatNumeric(
|
|||
const SimpleFormatter *MeasureFormat::getFormatterOrNull(
|
||||
const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index) const {
|
||||
width = getRegularWidth(width);
|
||||
SimpleFormatter *const (*unitPatterns)[MeasureFormatCacheData::PATTERN_COUNT] =
|
||||
&cache->patterns[unit.getIndex()][0];
|
||||
SimpleFormatter *const (*unitPatterns)[PATTERN_COUNT] = &cache->patterns[unit.getIndex()][0];
|
||||
if (unitPatterns[width][index] != NULL) {
|
||||
return unitPatterns[width][index];
|
||||
}
|
||||
|
@ -1162,8 +1164,7 @@ int32_t MeasureFormat::withPerUnitAndAppend(
|
|||
if (U_FAILURE(status)) {
|
||||
return offset;
|
||||
}
|
||||
const SimpleFormatter *perUnitFormatter =
|
||||
getFormatterOrNull(perUnit, width, MeasureFormatCacheData::PER_UNIT_INDEX);
|
||||
const SimpleFormatter *perUnitFormatter = getFormatterOrNull(perUnit, width, PER_UNIT_INDEX);
|
||||
if (perUnitFormatter != NULL) {
|
||||
const UnicodeString *params[] = {&formatted};
|
||||
perUnitFormatter->formatAndAppend(
|
||||
|
|
Loading…
Add table
Reference in a new issue