mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-13 17:01:16 +00:00
ICU-6613 fix udat crashers. See also ICU-6737
X-SVN-Rev: 25405
This commit is contained in:
parent
5013ce6d65
commit
dd4971d760
2 changed files with 149 additions and 16 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1996-2006, International Business Machines
|
||||
* Copyright (C) 1996-2009, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
@ -25,6 +25,18 @@
|
|||
|
||||
U_NAMESPACE_USE
|
||||
|
||||
/**
|
||||
* Verify that fmt is a SimpleDateFormat. Invalid error if not.
|
||||
* @param fmt the UDateFormat, definitely a DateFormat, maybe something else
|
||||
* @param status error code, will be set to failure if there is a familure or the fmt is NULL.
|
||||
*/
|
||||
static void verifyIsSimpleDateFormat(const UDateFormat* fmt, UErrorCode *status) {
|
||||
if(!U_FAILURE(*status) &&
|
||||
((DateFormat*)fmt)->getDynamicClassID()!=SimpleDateFormat::getStaticClassID()) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
U_CAPI UDateFormat* U_EXPORT2
|
||||
udat_open(UDateFormatStyle timeStyle,
|
||||
UDateFormatStyle dateStyle,
|
||||
|
@ -92,7 +104,7 @@ udat_clone(const UDateFormat *fmt,
|
|||
{
|
||||
if(U_FAILURE(*status)) return 0;
|
||||
|
||||
Format *res = ((SimpleDateFormat*)fmt)->clone();
|
||||
Format *res = ((DateFormat*)fmt)->clone();
|
||||
|
||||
if(res == 0) {
|
||||
*status = U_MEMORY_ALLOCATION_ERROR;
|
||||
|
@ -249,6 +261,7 @@ U_CAPI UDate U_EXPORT2
|
|||
udat_get2DigitYearStart( const UDateFormat *fmt,
|
||||
UErrorCode *status)
|
||||
{
|
||||
verifyIsSimpleDateFormat(fmt, status);
|
||||
if(U_FAILURE(*status)) return (UDate)0;
|
||||
return ((SimpleDateFormat*)fmt)->get2DigitYearStart(*status);
|
||||
}
|
||||
|
@ -258,6 +271,7 @@ udat_set2DigitYearStart( UDateFormat *fmt,
|
|||
UDate d,
|
||||
UErrorCode *status)
|
||||
{
|
||||
verifyIsSimpleDateFormat(fmt, status);
|
||||
if(U_FAILURE(*status)) return;
|
||||
((SimpleDateFormat*)fmt)->set2DigitYearStart(d, *status);
|
||||
}
|
||||
|
@ -269,6 +283,7 @@ udat_toPattern( const UDateFormat *fmt,
|
|||
int32_t resultLength,
|
||||
UErrorCode *status)
|
||||
{
|
||||
verifyIsSimpleDateFormat(fmt, status);
|
||||
if(U_FAILURE(*status)) return -1;
|
||||
|
||||
UnicodeString res;
|
||||
|
@ -286,7 +301,8 @@ udat_toPattern( const UDateFormat *fmt,
|
|||
return res.extract(result, resultLength, *status);
|
||||
}
|
||||
|
||||
// TBD: should this take an UErrorCode?
|
||||
// TODO: should this take an UErrorCode?
|
||||
// A: Yes. Of course.
|
||||
U_CAPI void U_EXPORT2
|
||||
udat_applyPattern( UDateFormat *format,
|
||||
UBool localized,
|
||||
|
@ -296,6 +312,11 @@ udat_applyPattern( UDateFormat *format,
|
|||
const UnicodeString pat((UBool)(patternLength == -1), pattern, patternLength);
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
verifyIsSimpleDateFormat(format, &status);
|
||||
if(U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(localized)
|
||||
((SimpleDateFormat*)format)->applyLocalizedPattern(pat, status);
|
||||
else
|
||||
|
@ -310,6 +331,7 @@ udat_getSymbols(const UDateFormat *fmt,
|
|||
int32_t resultLength,
|
||||
UErrorCode *status)
|
||||
{
|
||||
verifyIsSimpleDateFormat(fmt, status);
|
||||
if(U_FAILURE(*status)) return -1;
|
||||
|
||||
const DateFormatSymbols *syms =
|
||||
|
@ -414,10 +436,18 @@ udat_getSymbols(const UDateFormat *fmt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
// TODO: also needs an errorCode.
|
||||
U_CAPI int32_t U_EXPORT2
|
||||
udat_countSymbols( const UDateFormat *fmt,
|
||||
UDateFormatSymbolType type)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
verifyIsSimpleDateFormat(fmt, &status);
|
||||
if(U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const DateFormatSymbols *syms =
|
||||
((SimpleDateFormat*)fmt)->getDateFormatSymbols();
|
||||
int32_t count = 0;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
static void TestExtremeDates(void);
|
||||
static void TestAllLocales(void);
|
||||
static void TestRelativeCrash(void);
|
||||
|
||||
#define LEN(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
|
@ -48,6 +49,7 @@ void addDateForTest(TestNode** root)
|
|||
TESTCASE(TestDateFormatCalendar);
|
||||
TESTCASE(TestExtremeDates);
|
||||
TESTCASE(TestAllLocales);
|
||||
TESTCASE(TestRelativeCrash);
|
||||
}
|
||||
/* Testing the DateFormat API */
|
||||
static void TestDateFormat()
|
||||
|
@ -806,7 +808,8 @@ static void TestDateFormatCalendar() {
|
|||
}
|
||||
|
||||
/*INTERNAL FUNCTIONS USED*/
|
||||
static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t index, const char* expected)
|
||||
/* N.B.: use idx instead of index to avoid 'shadow' warnings in strict mode. */
|
||||
static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
|
||||
{
|
||||
UChar *pattern=NULL;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
@ -817,13 +820,13 @@ static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
pattern=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1));
|
||||
u_uastrcpy(pattern, expected);
|
||||
resultlength=0;
|
||||
resultlengthout=udat_getSymbols(datfor, type, index , NULL, resultlength, &status);
|
||||
resultlengthout=udat_getSymbols(datfor, type, idx , NULL, resultlength, &status);
|
||||
if(status==U_BUFFER_OVERFLOW_ERROR)
|
||||
{
|
||||
status=U_ZERO_ERROR;
|
||||
resultlength=resultlengthout+1;
|
||||
result=(UChar*)malloc(sizeof(UChar) * resultlength);
|
||||
udat_getSymbols(datfor, type, index, result, resultlength, &status);
|
||||
udat_getSymbols(datfor, type, idx, result, resultlength, &status);
|
||||
|
||||
}
|
||||
if(U_FAILURE(status))
|
||||
|
@ -841,7 +844,7 @@ static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
free(pattern);
|
||||
}
|
||||
|
||||
static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t index, const char* expected)
|
||||
static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
|
||||
{
|
||||
UChar *result=NULL;
|
||||
UChar *value=NULL;
|
||||
|
@ -850,7 +853,7 @@ static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
|
||||
value=(UChar*)malloc(sizeof(UChar) * (strlen(expected) + 1));
|
||||
u_uastrcpy(value, expected);
|
||||
udat_setSymbols(datfor, type, index, value, u_strlen(value), &status);
|
||||
udat_setSymbols(datfor, type, idx, value, u_strlen(value), &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: Error in udat_setSymbols() %s\n", myErrorName(status) );
|
||||
|
@ -858,12 +861,12 @@ static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
}
|
||||
|
||||
resultlength=0;
|
||||
resultlengthout=udat_getSymbols(datfor, type, index, NULL, resultlength, &status);
|
||||
resultlengthout=udat_getSymbols(datfor, type, idx, NULL, resultlength, &status);
|
||||
if(status==U_BUFFER_OVERFLOW_ERROR){
|
||||
status=U_ZERO_ERROR;
|
||||
resultlength=resultlengthout+1;
|
||||
result=(UChar*)malloc(sizeof(UChar) * resultlength);
|
||||
udat_getSymbols(datfor, type, index, result, resultlength, &status);
|
||||
udat_getSymbols(datfor, type, idx, result, resultlength, &status);
|
||||
}
|
||||
if(U_FAILURE(status)){
|
||||
log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n",
|
||||
|
@ -883,7 +886,7 @@ static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, in
|
|||
}
|
||||
|
||||
|
||||
static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatSymbolType type, int32_t index)
|
||||
static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatSymbolType type, int32_t idx)
|
||||
{
|
||||
UChar *result=NULL;
|
||||
UChar *value=NULL;
|
||||
|
@ -891,12 +894,12 @@ static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatS
|
|||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
resultlength=0;
|
||||
resultlengthout=udat_getSymbols(from, type, index , NULL, resultlength, &status);
|
||||
resultlengthout=udat_getSymbols(from, type, idx , NULL, resultlength, &status);
|
||||
if(status==U_BUFFER_OVERFLOW_ERROR){
|
||||
status=U_ZERO_ERROR;
|
||||
resultlength=resultlengthout+1;
|
||||
result=(UChar*)malloc(sizeof(UChar) * resultlength);
|
||||
udat_getSymbols(from, type, index, result, resultlength, &status);
|
||||
udat_getSymbols(from, type, idx, result, resultlength, &status);
|
||||
}
|
||||
if(U_FAILURE(status)){
|
||||
log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
|
||||
|
@ -904,7 +907,7 @@ static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatS
|
|||
}
|
||||
|
||||
resultlength=resultlengthout+1;
|
||||
udat_setSymbols(to, type, index, result, resultlength, &status);
|
||||
udat_setSymbols(to, type, idx, result, resultlength, &status);
|
||||
if(U_FAILURE(status))
|
||||
{
|
||||
log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
|
||||
|
@ -912,12 +915,12 @@ static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatS
|
|||
}
|
||||
|
||||
resultlength=0;
|
||||
resultlengthout=udat_getSymbols(to, type, index, NULL, resultlength, &status);
|
||||
resultlengthout=udat_getSymbols(to, type, idx, NULL, resultlength, &status);
|
||||
if(status==U_BUFFER_OVERFLOW_ERROR){
|
||||
status=U_ZERO_ERROR;
|
||||
resultlength=resultlengthout+1;
|
||||
value=(UChar*)malloc(sizeof(UChar) * resultlength);
|
||||
udat_getSymbols(to, type, index, value, resultlength, &status);
|
||||
udat_getSymbols(to, type, idx, value, resultlength, &status);
|
||||
}
|
||||
if(U_FAILURE(status)){
|
||||
log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n",
|
||||
|
@ -1064,4 +1067,104 @@ static void TestAllLocales(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void TestRelativeCrash(void) {
|
||||
static const UChar tzName[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 };
|
||||
static const UDate aDate = -631152000000.0;
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UErrorCode expectStatus = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
UDateFormat icudf;
|
||||
|
||||
icudf = udat_open(UDAT_NONE, UDAT_SHORT_RELATIVE, "en", tzName, -1, NULL, 0, &status);
|
||||
if ( U_SUCCESS(status) ) {
|
||||
const char *what = "???";
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_set2DigitYearStart";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_set2DigitYearStart(icudf, aDate, &subStatus);
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
{
|
||||
/* clone works polymorphically. try it anyways */
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
UDateFormat *oth;
|
||||
what = "clone";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
oth = udat_clone(icudf, &subStatus);
|
||||
if(subStatus == U_ZERO_ERROR) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
udat_close(oth); /* ? */
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_get2DigitYearStart";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_get2DigitYearStart(icudf, &subStatus);
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_toPattern";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_toPattern(icudf, FALSE,NULL,0, &subStatus);
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_applyPattern";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_applyPattern(icudf, FALSE,tzName,-1);
|
||||
subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* what it should be, if this took an errorcode. */
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_getSymbols";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_getSymbols(icudf, UDAT_ERAS,0,NULL,0, &subStatus); /* bogus values */
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
{
|
||||
UErrorCode subStatus = U_ZERO_ERROR;
|
||||
what = "udat_countSymbols";
|
||||
log_verbose("Trying %s on a relative date..\n", what);
|
||||
udat_countSymbols(icudf, UDAT_ERAS);
|
||||
subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* should have an errorcode. */
|
||||
if(subStatus == expectStatus) {
|
||||
log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
|
||||
} else {
|
||||
log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
|
||||
}
|
||||
}
|
||||
|
||||
udat_close(icudf);
|
||||
} else {
|
||||
log_err("FAIL: err %s\n", u_errorName(status));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
Loading…
Add table
Reference in a new issue