Skip to content

Commit 3d8c971

Browse files
authored
Merge pull request godotengine#60215 from rohanrhu/fix-invalid-datetime-crash
Fix crash when parsing invalid datetime string
2 parents 3639c27 + 2b8eb12 commit 3d8c971

File tree

1 file changed

+50
-46
lines changed

1 file changed

+50
-46
lines changed

core/os/time.cpp

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -124,50 +124,54 @@ VARIANT_ENUM_CAST(Time::Weekday);
124124
} \
125125
}
126126

127-
#define PARSE_ISO8601_STRING \
128-
int64_t year = UNIX_EPOCH_YEAR_AD; \
129-
Month month = MONTH_JANUARY; \
130-
uint8_t day = 1; \
131-
uint8_t hour = 0; \
132-
uint8_t minute = 0; \
133-
uint8_t second = 0; \
134-
{ \
135-
bool has_date = false, has_time = false; \
136-
String date, time; \
137-
if (p_datetime.find_char('T') > 0) { \
138-
has_date = has_time = true; \
139-
PackedStringArray array = p_datetime.split("T"); \
140-
date = array[0]; \
141-
time = array[1]; \
142-
} else if (p_datetime.find_char(' ') > 0) { \
143-
has_date = has_time = true; \
144-
PackedStringArray array = p_datetime.split(" "); \
145-
date = array[0]; \
146-
time = array[1]; \
147-
} else if (p_datetime.find_char('-', 1) > 0) { \
148-
has_date = true; \
149-
date = p_datetime; \
150-
} else if (p_datetime.find_char(':') > 0) { \
151-
has_time = true; \
152-
time = p_datetime; \
153-
} \
154-
/* Set the variables from the contents of the string. */ \
155-
if (has_date) { \
156-
PackedInt32Array array = date.split_ints("-", false); \
157-
year = array[0]; \
158-
month = (Month)array[1]; \
159-
day = array[2]; \
160-
/* Handle negative years. */ \
161-
if (p_datetime.find_char('-') == 0) { \
162-
year *= -1; \
163-
} \
164-
} \
165-
if (has_time) { \
166-
PackedInt32Array array = time.split_ints(":", false); \
167-
hour = array[0]; \
168-
minute = array[1]; \
169-
second = array[2]; \
170-
} \
127+
#define PARSE_ISO8601_STRING(ret) \
128+
int64_t year = UNIX_EPOCH_YEAR_AD; \
129+
Month month = MONTH_JANUARY; \
130+
uint8_t day = 1; \
131+
uint8_t hour = 0; \
132+
uint8_t minute = 0; \
133+
uint8_t second = 0; \
134+
{ \
135+
bool has_date = false, has_time = false; \
136+
String date, time; \
137+
if (p_datetime.find_char('T') > 0) { \
138+
has_date = has_time = true; \
139+
PackedStringArray array = p_datetime.split("T"); \
140+
ERR_FAIL_COND_V_MSG(array.size() < 2, ret, "Invalid ISO 8601 date/time string."); \
141+
date = array[0]; \
142+
time = array[1]; \
143+
} else if (p_datetime.find_char(' ') > 0) { \
144+
has_date = has_time = true; \
145+
PackedStringArray array = p_datetime.split(" "); \
146+
ERR_FAIL_COND_V_MSG(array.size() < 2, ret, "Invalid ISO 8601 date/time string."); \
147+
date = array[0]; \
148+
time = array[1]; \
149+
} else if (p_datetime.find_char('-', 1) > 0) { \
150+
has_date = true; \
151+
date = p_datetime; \
152+
} else if (p_datetime.find_char(':') > 0) { \
153+
has_time = true; \
154+
time = p_datetime; \
155+
} \
156+
/* Set the variables from the contents of the string. */ \
157+
if (has_date) { \
158+
PackedInt32Array array = date.split_ints("-", false); \
159+
ERR_FAIL_COND_V_MSG(array.size() < 3, ret, "Invalid ISO 8601 date string."); \
160+
year = array[0]; \
161+
month = (Month)array[1]; \
162+
day = array[2]; \
163+
/* Handle negative years. */ \
164+
if (p_datetime.find_char('-') == 0) { \
165+
year *= -1; \
166+
} \
167+
} \
168+
if (has_time) { \
169+
PackedInt32Array array = time.split_ints(":", false); \
170+
ERR_FAIL_COND_V_MSG(array.size() < 3, ret, "Invalid ISO 8601 time string."); \
171+
hour = array[0]; \
172+
minute = array[1]; \
173+
second = array[2]; \
174+
} \
171175
}
172176

173177
#define EXTRACT_FROM_DICTIONARY \
@@ -253,7 +257,7 @@ String Time::get_time_string_from_unix_time(int64_t p_unix_time_val) const {
253257
}
254258

255259
Dictionary Time::get_datetime_dict_from_string(String p_datetime, bool p_weekday) const {
256-
PARSE_ISO8601_STRING
260+
PARSE_ISO8601_STRING(Dictionary())
257261
Dictionary dict;
258262
dict[YEAR_KEY] = year;
259263
dict[MONTH_KEY] = (uint8_t)month;
@@ -293,7 +297,7 @@ int64_t Time::get_unix_time_from_datetime_dict(const Dictionary p_datetime) cons
293297
}
294298

295299
int64_t Time::get_unix_time_from_datetime_string(String p_datetime) const {
296-
PARSE_ISO8601_STRING
300+
PARSE_ISO8601_STRING(-1)
297301
VALIDATE_YMDHMS(0)
298302
YMD_TO_DAY_NUMBER
299303
return day_number * SECONDS_PER_DAY + hour * 3600 + minute * 60 + second;

0 commit comments

Comments
 (0)