ICU-6613 fix udat crashers. See also ICU-6737

X-SVN-Rev: 25405
This commit is contained in:
Steven R. Loomis 2009-02-14 02:29:08 +00:00
parent 5013ce6d65
commit dd4971d760
2 changed files with 149 additions and 16 deletions

View file

@ -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;

View file

@ -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 */