ECC-1777: Validate dataDate and dataTime on input

This commit is contained in:
shahramn 2024-02-28 15:36:21 +00:00
parent 8b4d1eb323
commit e2368676b3
5 changed files with 73 additions and 54 deletions

View File

@ -213,6 +213,38 @@ int is_date_valid(long year, long month, long day, long hour, long minute, doubl
return 1;
}
// Return 1 if input date is valid. Otherwise 0
// Note: In the 24-hour time notation, the day begins at midnight, 00:00 or 0:00,
// and the last minute of the day begins at 23:59.
// Where convenient, the notation 24:00 may also be used to refer to midnight
// at the end of a given date — that is, 24:00 of one day is the same time
// as 00:00 of the following day
int is_time_valid(long number)
{
// number should be 4 digits i.e., HHMM
// Check if the number is a four-digit integer
if (number < 0 || number > 9999) {
return 0;
}
// Extract hours and minutes
long hours = number / 100; // Get the first two digits as hours
long minutes = number % 100; // Get the last two digits as minutes
// Check if hours are within the valid range (00-23)
if (hours < 0 || hours > 24) {
return 0;
}
// Check if minutes are within the valid range (00-59)
if (minutes < 0 || minutes > 59) {
return 0;
}
// All checks pass
return 1;
}
static float float_epsilon(void)
{
float floatEps = 1.0;

View File

@ -1328,6 +1328,7 @@ char* codes_getenv(const char* name);
int codes_check_grib_ieee_packing_value(int value);
int codes_flush_sync_close_file(FILE* f);
int is_date_valid(long year, long month, long day, long hour, long minute, double second);
int is_time_valid(long number); // number is HHMM
int compute_scaled_value_and_scale_factor(double input, int64_t scaled_value_max, int64_t scale_factor_max, int64_t* ret_value, int64_t* ret_factor);
/* grib_util.cc*/

View File

@ -123,9 +123,9 @@ static void dump(grib_accessor* a, grib_dumper* dumper)
static int unpack_long(grib_accessor* a, long* val, size_t* len)
{
int ret = 0;
grib_accessor_g2date* self = (grib_accessor_g2date*)a;
const grib_accessor_g2date* self = (grib_accessor_g2date*)a;
int ret = 0;
long year = 0;
long month = 0;
long day = 0;
@ -145,13 +145,12 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
return GRIB_SUCCESS;
}
/* TODO: Check for a valid date */
static int pack_long(grib_accessor* a, const long* val, size_t* len)
{
int ret;
long v = val[0];
grib_accessor_g2date* self = (grib_accessor_g2date*)a;
const grib_accessor_g2date* self = (grib_accessor_g2date*)a;
int ret = GRIB_SUCCESS;
long v = val[0];
long year = 0;
long month = 0;
long day = 0;
@ -165,6 +164,12 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len)
v %= 100;
day = v;
if (!is_date_valid(year, month, day, 0, 0, 0)) {
// ECC-1777: For now just a warning. Will later change to an error
fprintf(stderr, "ECCODES WARNING : %s:%s: Date is not valid! year=%ld month=%ld day=%ld\n",
a->cclass->name, __func__, year, month, day);
}
if ((ret = grib_set_long_internal(grib_handle_of_accessor(a), self->day, day)) != GRIB_SUCCESS)
return ret;
if ((ret = grib_set_long_internal(grib_handle_of_accessor(a), self->month, month)) != GRIB_SUCCESS)

View File

@ -126,11 +126,10 @@ static void dump(grib_accessor* a, grib_dumper* dumper)
static int unpack_long(grib_accessor* a, long* val, size_t* len)
{
const grib_accessor_time* self = (grib_accessor_time*)a;
int ret = 0;
grib_accessor_time* self = (grib_accessor_time*)a;
long hour = 0;
long minute = 0;
long second = 0;
long hour = 0, minute = 0, second = 0;
grib_handle* hand = grib_handle_of_accessor(a);
if ((ret = grib_get_long_internal(hand, self->hour, &hour)) != GRIB_SUCCESS)
@ -160,54 +159,24 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
return GRIB_SUCCESS;
}
// In the 24-hour time notation, the day begins at midnight, 00:00 or 0:00,
// and the last minute of the day begins at 23:59.
// Where convenient, the notation 24:00 may also be used to refer to midnight
// at the end of a given date — that is, 24:00 of one day is the same time
// as 00:00 of the following day
#if 0
static bool isValidTime(long number)
{
// Check if the number is a four-digit integer
if (number < 0 || number > 9999) {
return false;
}
// Extract hours and minutes
long hours = number / 100; // Get the first two digits as hours
long minutes = number % 100; // Get the last two digits as minutes
// Check if hours are within the valid range (00-23)
if (hours < 0 || hours > 24) {
return false;
}
// Check if minutes are within the valid range (00-59)
if (minutes < 0 || minutes > 59) {
return false;
}
// All checks pass
return true;
}
#endif
static int pack_long(grib_accessor* a, const long* val, size_t* len)
{
const grib_accessor_time* self = (grib_accessor_time*)a;
int ret = 0;
long v = val[0];
grib_accessor_time* self = (grib_accessor_time*)a;
grib_handle* hand = grib_handle_of_accessor(a);
long hour = 0;
long minute = 0;
long second = 0;
long hour = 0, minute = 0, second = 0;
if (*len != 1)
return GRIB_WRONG_ARRAY_SIZE;
// if (!isValidTime(v)) {
if (!is_time_valid(v)) {
// ECC-1777: For now just a warning. Will later change to an error
fprintf(stderr, "ECCODES WARNING : %s:%s: Time is not valid! hour=%ld min=%ld sec=%ld\n",
a->cclass->name, __func__, hour, minute, second);
// return GRIB_ENCODING_ERROR;
// }
}
hour = v / 100;
minute = v % 100;

View File

@ -95,6 +95,18 @@ status=$?
set -e
[ $status -ne 0 ]
# Bad date
# ---------
input=$ECCODES_SAMPLES_PATH/GRIB2.tmpl
${tools_dir}/grib_set -s dataDate=20180229 $input $outfile > $temp 2>&1
cat $temp
grep -q "Date is not valid" $temp
${tools_dir}/grib_set -s dataTime=4261 $input $outfile > $temp 2>&1
cat $temp
grep -q "Time is not valid" $temp
# ECC-1359: string that can be converted to an integer
# ---------------------------------------------------
${tools_dir}/grib_set -s month:s=6 $ECCODES_SAMPLES_PATH/GRIB2.tmpl $outfile