diff options
author | Lars Henriksen <LarsHenriksen@get2net.dk> | 2017-11-06 19:30:32 +0100 |
---|---|---|
committer | Lukas Fleischer <lfleischer@calcurse.org> | 2018-08-25 10:03:28 +0200 |
commit | fd635150a8bf131c3a8cec2bf41feaf469832dc5 (patch) | |
tree | 7349af62e6d6648217efcc0c3b704a7422048e96 | |
parent | c45da5f5ca550215588ba9483eef62f2a214addb (diff) | |
download | calcurse-fd635150a8bf131c3a8cec2bf41feaf469832dc5.tar.gz calcurse-fd635150a8bf131c3a8cec2bf41feaf469832dc5.zip |
Start and end time validation.
All appointment times are checked for validity. Overflow by time
arithmetic is detected. End times are checked when appointments
are moved. Three functions are involved: parse_datetime(),
parse_duration() and parse_date_duration(); they all have a
new argument for validation purposes.
Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
-rw-r--r-- | src/calcurse.h | 6 | ||||
-rw-r--r-- | src/utils.c | 49 |
2 files changed, 47 insertions, 8 deletions
diff --git a/src/calcurse.h b/src/calcurse.h index 178af1f..88a0916 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -1162,9 +1162,9 @@ int parse_date_interactive(const char *, int *, int *, int *); int check_sec(time_t *); int check_time(unsigned, unsigned); int parse_time(const char *, unsigned *, unsigned *); -int parse_duration(const char *, unsigned *); -int parse_date_duration(const char *, unsigned *); -int parse_datetime(const char *, long *); +int parse_duration(const char *, unsigned *, time_t); +int parse_date_duration(const char *, unsigned *, time_t); +int parse_datetime(const char *, time_t *, time_t); void file_close(FILE *, const char *); void psleep(unsigned); int fork_exec(int *, int *, const char *, const char *const *); diff --git a/src/utils.c b/src/utils.c index 8728dfb..0690d4e 100644 --- a/src/utils.c +++ b/src/utils.c @@ -936,10 +936,11 @@ parse_date_interactive(const char *datestr, int *year, int *month, int *day) /* * Convert a date duration string into a number of days. + * If start is non-zero, the final end time is validated. * * Returns 1 on success and 0 on failure. */ -int parse_date_duration(const char *string, unsigned *days) +int parse_date_duration(const char *string, unsigned *days, time_t start) { enum { STATE_INITIAL, @@ -1000,6 +1001,17 @@ int parse_date_duration(const char *string, unsigned *days) return 0; dur += in; + if (start) { + /* wanted: start = start + dur * DAYINSEC */ + int p, s; + if (overflow_mul(dur, DAYINSEC, &p)) + return 0; + if (overflow_add(start, p, &s)) + return 0; + start = s; + if (!check_sec(&start)) + return 0; + } *days = dur; return 1; @@ -1051,6 +1063,7 @@ int parse_time(const char *string, unsigned *hour, unsigned *minute) /* * Converts a duration string into minutes. + * If start time is non-zero, the final end time is validated. * * Allowed formats (noted as regular expressions): * @@ -1062,7 +1075,7 @@ int parse_time(const char *string, unsigned *hour, unsigned *minute) * * Returns 1 on success and 0 on failure. */ -int parse_duration(const char *string, unsigned *duration) +int parse_duration(const char *string, unsigned *duration, time_t start) { enum { STATE_INITIAL, @@ -1140,13 +1153,23 @@ int parse_duration(const char *string, unsigned *duration) denom = 1; } } - if ((state == STATE_HHMM_MM && in >= HOURINMIN) || ((state == STATE_DDHHMM_HH || state == STATE_DDHHMM_MM) && in > 0)) return 0; - dur += in; + if (start) { + /* wanted: end = start + dur * MININSEC */ + time_t end; + int p, s; + if (overflow_mul(dur, MININSEC, &p)) + return 0; + if (overflow_add(start, p, &s)) + return 0; + end = s; + if (!check_sec(&end) || end < start) + return 0; + } *duration = dur; return 1; @@ -1161,10 +1184,13 @@ int parse_duration(const char *string, unsigned *duration) * updated and the date remains the same. If the string contains both a date * and a time, the time stamp is updated to match the given string. * + * The final time is validated. In addition, if a positive duration is given, + * time + duration validated (zero duration needs no validation). + * * Returns a positive value on success and 0 on failure. The least-significant * bit is set if the date was updated. Bit 1 is set if the time was updated. */ -int parse_datetime(const char *string, long *ts) +int parse_datetime(const char *string, time_t *ts, time_t dur) { char *t = mem_strdup(string); char *p = strchr(t, ' '); @@ -1197,6 +1223,19 @@ int parse_datetime(const char *string, long *ts) *ts = update_time_in_date(*ts, hour, minute); mem_free(t); + /* Is the resulting time a valid (start or end) time? */ + if (!check_sec(ts)) + return 0; + /* Is the resulting time + dur a valid end time? */ + if (dur) { + /* want: sec = *ts + dur */ + int s; + if (overflow_add(*ts, dur, &s)) + return 0; + time_t sec = s; + if (!check_sec(&sec)) + return 0; + } return ret; } |