aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-03-20 14:25:05 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-03-20 14:30:48 +0200
commit387d98b80d9f383c4c7708a42444472cb89dd42b (patch)
tree4233a4e5fc05c3b80a10afafd6f7647542b283bc
parent92fd3c03c5123e8d886d5de642cfc8e4606d42e6 (diff)
Add extra validation for date, dateTime, and gMonthDay per XML Schema 1.1
-rw-r--r--libxsde/xsde/cxx/parser/validating/date-time.cxx36
-rw-r--r--libxsde/xsde/cxx/parser/validating/date.cxx36
-rw-r--r--libxsde/xsde/cxx/parser/validating/gmonth-day.cxx23
-rw-r--r--libxsde/xsde/cxx/serializer/validating/date-time.cxx26
-rw-r--r--libxsde/xsde/cxx/serializer/validating/date.cxx26
-rw-r--r--libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx23
6 files changed, 156 insertions, 14 deletions
diff --git a/libxsde/xsde/cxx/parser/validating/date-time.cxx b/libxsde/xsde/cxx/parser/validating/date-time.cxx
index 06d66e9..268d270 100644
--- a/libxsde/xsde/cxx/parser/validating/date-time.cxx
+++ b/libxsde/xsde/cxx/parser/validating/date-time.cxx
@@ -193,11 +193,7 @@ namespace xsde
day_ = 10 * (d1 - '0') + (d2 - '0');
- if (day_ < 1 || day_ > 31)
- {
- _schema_error (schema_error::invalid_date_time_value);
- return;
- }
+ // Note: day validated below.
// month
//
@@ -241,6 +237,36 @@ namespace xsde
? (-2147483647 - 1)
: -static_cast<int> (ul))
: static_cast<int> (ul);
+
+ // Validate day according to the XML Schema 1.1 specification:
+ //
+ // The day value must be no more than 30 if month is one of 4, 6, 9,
+ // or 11, no more than 28 if month is 2 and year is not divisible by
+ // 4, or is divisible by 100 but not by 400, and no more than 29 if
+ // month is 2 and year is divisible by 400, or by 4 but not by 100.
+ //
+ unsigned short max_day = 31;
+ switch (month_)
+ {
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ max_day = 30;
+ break;
+ case 2:
+ max_day = ((year_ % 400 == 0) ||
+ (year_ % 4 == 0 && year_ % 100 != 0) ? 29 : 28);
+ break;
+ default:
+ break;
+ }
+
+ if (day_ < 1 || day_ > max_day)
+ {
+ _schema_error (schema_error::invalid_date_time_value);
+ return;
+ }
}
date_time date_time_pimpl::
diff --git a/libxsde/xsde/cxx/parser/validating/date.cxx b/libxsde/xsde/cxx/parser/validating/date.cxx
index a021e4c..ec38f09 100644
--- a/libxsde/xsde/cxx/parser/validating/date.cxx
+++ b/libxsde/xsde/cxx/parser/validating/date.cxx
@@ -120,11 +120,7 @@ namespace xsde
day_ = 10 * (d1 - '0') + (d2 - '0');
- if (day_ < 1 || day_ > 31)
- {
- _schema_error (schema_error::invalid_date_value);
- return;
- }
+ // Note: day validated below.
// zone
//
@@ -165,6 +161,36 @@ namespace xsde
? (-2147483647 - 1)
: -static_cast<int> (ul))
: static_cast<int> (ul);
+
+ // Validate day according to the XML Schema 1.1 specification:
+ //
+ // The day value must be no more than 30 if month is one of 4, 6, 9,
+ // or 11, no more than 28 if month is 2 and year is not divisible by
+ // 4, or is divisible by 100 but not by 400, and no more than 29 if
+ // month is 2 and year is divisible by 400, or by 4 but not by 100.
+ //
+ unsigned short max_day = 31;
+ switch (month_)
+ {
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ max_day = 30;
+ break;
+ case 2:
+ max_day = ((year_ % 400 == 0) ||
+ (year_ % 4 == 0 && year_ % 100 != 0) ? 29 : 28);
+ break;
+ default:
+ break;
+ }
+
+ if (day_ < 1 || day_ > max_day)
+ {
+ _schema_error (schema_error::invalid_date_value);
+ return;
+ }
}
date date_pimpl::
diff --git a/libxsde/xsde/cxx/parser/validating/gmonth-day.cxx b/libxsde/xsde/cxx/parser/validating/gmonth-day.cxx
index a972855..5d5efd7 100644
--- a/libxsde/xsde/cxx/parser/validating/gmonth-day.cxx
+++ b/libxsde/xsde/cxx/parser/validating/gmonth-day.cxx
@@ -100,7 +100,28 @@ namespace xsde
day_ = 10 * (d1 - '0') + (d2 - '0');
- if (day_ < 1 || day_ > 31)
+ // Validate day according to the XML Schema 1.1 specification:
+ //
+ // The day value must be no more than 30 if month is one of 4, 6, 9,
+ // or 11, and no more than 29 if month is 2.
+ //
+ unsigned short max_day = 31;
+ switch (month_)
+ {
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ max_day = 30;
+ break;
+ case 2:
+ max_day = 29;
+ break;
+ default:
+ break;
+ }
+
+ if (day_ < 1 || day_ > max_day)
{
_schema_error (schema_error::invalid_gmonth_day_value);
return;
diff --git a/libxsde/xsde/cxx/serializer/validating/date-time.cxx b/libxsde/xsde/cxx/serializer/validating/date-time.cxx
index 7d9db17..d5069be 100644
--- a/libxsde/xsde/cxx/serializer/validating/date-time.cxx
+++ b/libxsde/xsde/cxx/serializer/validating/date-time.cxx
@@ -38,7 +38,31 @@ namespace xsde
unsigned short tm = value_.minutes ();
double s = value_.seconds ();
- if (y != 0 && m > 0 && m < 13 && d > 0 && d < 32 &&
+ // Validate day according to the XML Schema 1.1 specification:
+ //
+ // The day value must be no more than 30 if month is one of 4, 6, 9,
+ // or 11, no more than 28 if month is 2 and year is not divisible by
+ // 4, or is divisible by 100 but not by 400, and no more than 29 if
+ // month is 2 and year is divisible by 400, or by 4 but not by 100.
+ //
+ unsigned short max_day = 31;
+ switch (m)
+ {
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ max_day = 30;
+ break;
+ case 2:
+ max_day = ((y % 400 == 0) ||
+ (y % 4 == 0 && y % 100 != 0) ? 29 : 28);
+ break;
+ default:
+ break;
+ }
+
+ if (y != 0 && m > 0 && m < 13 && d > 0 && d <= max_day &&
((h < 24 && tm < 60 && s >= 0.0 && s < 60.0) ||
(h == 24 && tm == 0 && s == 0.0)) &&
(!value_.zone_present () || bits::valid_time_zone (value_)))
diff --git a/libxsde/xsde/cxx/serializer/validating/date.cxx b/libxsde/xsde/cxx/serializer/validating/date.cxx
index 27beb79..fd1c8d6 100644
--- a/libxsde/xsde/cxx/serializer/validating/date.cxx
+++ b/libxsde/xsde/cxx/serializer/validating/date.cxx
@@ -32,7 +32,31 @@ namespace xsde
unsigned short m = value_.month ();
unsigned short d = value_.day ();
- if (y != 0 && m > 0 && m < 13 && d > 0 && d < 32 &&
+ // Validate day according to the XML Schema 1.1 specification:
+ //
+ // The day value must be no more than 30 if month is one of 4, 6, 9,
+ // or 11, no more than 28 if month is 2 and year is not divisible by
+ // 4, or is divisible by 100 but not by 400, and no more than 29 if
+ // month is 2 and year is divisible by 400, or by 4 but not by 100.
+ //
+ unsigned short max_day = 31;
+ switch (m)
+ {
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ max_day = 30;
+ break;
+ case 2:
+ max_day = ((y % 400 == 0) ||
+ (y % 4 == 0 && y % 100 != 0) ? 29 : 28);
+ break;
+ default:
+ break;
+ }
+
+ if (y != 0 && m > 0 && m < 13 && d > 0 && d <= max_day &&
(!value_.zone_present () || bits::valid_time_zone (value_)))
{
#ifdef XSDE_SNPRINTF
diff --git a/libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx b/libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx
index dc044fd..ea83451 100644
--- a/libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx
+++ b/libxsde/xsde/cxx/serializer/validating/gmonth-day.cxx
@@ -31,7 +31,28 @@ namespace xsde
unsigned short m = value_.month ();
unsigned short d = value_.day ();
- if (m > 0 && m < 13 && d > 0 && d < 32 &&
+ // Validate day according to the XML Schema 1.1 specification:
+ //
+ // The day value must be no more than 30 if month is one of 4, 6, 9,
+ // or 11, and no more than 29 if month is 2.
+ //
+ unsigned short max_day = 31;
+ switch (m)
+ {
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ max_day = 30;
+ break;
+ case 2:
+ max_day = 29;
+ break;
+ default:
+ break;
+ }
+
+ if (m > 0 && m < 13 && d > 0 && d <= max_day &&
(!value_.zone_present () || bits::valid_time_zone (value_)))
{
#ifdef XSDE_SNPRINTF