From e269f09438ad1bfaef044c5781615cba45ab7690 Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Thu, 22 Nov 2012 22:23:58 +0100 Subject: Replace localtime() with localtime_r() Since the result of localtime() is stored in a statically allocated structure, data was overwritten when a context switch occurred during (or shortly after) the execution of localtime(), potentially resulting in critical data corruption. BUG#7 and BUG#8 are likely related. This patch converts all usages of localtime() with localtime_r(), which is thread-safe. Reported-by: Baptiste Jonglez Reported-by: Erik Saule Signed-off-by: Lukas Fleischer --- src/utils.c | 81 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 34 deletions(-) (limited to 'src/utils.c') diff --git a/src/utils.c b/src/utils.c index 14de867..da8eade 100644 --- a/src/utils.c +++ b/src/utils.c @@ -337,18 +337,26 @@ long get_item_time(long date) int get_item_hour(long date) { - return (localtime((time_t *) & date))->tm_hour; + struct tm lt; + + localtime_r((time_t *)&date, <); + return lt.tm_hour; } int get_item_min(long date) { - return (localtime((time_t *) & date))->tm_min; + struct tm lt; + + localtime_r((time_t *)&date, <); + return lt.tm_min; } long date2sec(struct date day, unsigned hour, unsigned min) { time_t t = now(); - struct tm start = *(localtime(&t)); + struct tm start; + + localtime_r(&t, &start); start.tm_mon = day.mm - 1; start.tm_mday = day.dd; @@ -367,14 +375,14 @@ long date2sec(struct date day, unsigned hour, unsigned min) /* Return a string containing the date, given a date in seconds. */ char *date_sec2date_str(long sec, const char *datefmt) { - struct tm *lt; + struct tm lt; char *datestr = (char *)mem_calloc(BUFSIZ, sizeof(char)); if (sec == 0) strncpy(datestr, "0", BUFSIZ); else { - lt = localtime((time_t *) & sec); - strftime(datestr, BUFSIZ, datefmt, lt); + localtime_r((time_t *)&sec, <); + strftime(datestr, BUFSIZ, datefmt, <); } return datestr; @@ -389,8 +397,9 @@ void date_sec2date_fmt(long sec, const char *fmt, char *datef) setlocale (LC_ALL, "C"); #endif - struct tm *lt = localtime((time_t *)&sec); - strftime(datef, BUFSIZ, fmt, lt); + struct tm lt; + localtime_r((time_t *)&sec, <); + strftime(datef, BUFSIZ, fmt, <); #if ENABLE_NLS setlocale (LC_ALL, locale_old); @@ -403,15 +412,15 @@ void date_sec2date_fmt(long sec, const char *fmt, char *datef) */ long date_sec_change(long date, int delta_month, int delta_day) { - struct tm *lt; + struct tm lt; time_t t; t = date; - lt = localtime(&t); - lt->tm_mon += delta_month; - lt->tm_mday += delta_day; - lt->tm_isdst = -1; - t = mktime(lt); + localtime_r(&t, <); + lt.tm_mon += delta_month; + lt.tm_mday += delta_day; + lt.tm_isdst = -1; + t = mktime(<); EXIT_IF(t == -1, _("failure in mktime")); return t; @@ -423,14 +432,14 @@ long date_sec_change(long date, int delta_month, int delta_day) */ long update_time_in_date(long date, unsigned hr, unsigned mn) { - struct tm *lt; + struct tm lt; time_t t, new_date; t = date; - lt = localtime(&t); - lt->tm_hour = hr; - lt->tm_min = mn; - new_date = mktime(lt); + localtime_r(&t, <); + lt.tm_hour = hr; + lt.tm_min = mn; + new_date = mktime(<); EXIT_IF(new_date == -1, _("error in mktime")); return new_date; @@ -442,7 +451,7 @@ long update_time_in_date(long date, unsigned hr, unsigned mn) */ long get_sec_date(struct date date) { - struct tm *ptrtime; + struct tm ptrtime; time_t timer; long long_date; char current_day[] = "dd "; @@ -451,10 +460,10 @@ long get_sec_date(struct date date) if (date.yyyy == 0 && date.mm == 0 && date.dd == 0) { timer = time(NULL); - ptrtime = localtime(&timer); - strftime(current_day, strlen(current_day), "%d", ptrtime); - strftime(current_month, strlen(current_month), "%m", ptrtime); - strftime(current_year, strlen(current_year), "%Y", ptrtime); + localtime_r(&timer, &ptrtime); + strftime(current_day, strlen(current_day), "%d", &ptrtime); + strftime(current_month, strlen(current_month), "%m", &ptrtime); + strftime(current_year, strlen(current_year), "%Y", &ptrtime); date.mm = atoi(current_month); date.dd = atoi(current_day); date.yyyy = atoi(current_year); @@ -518,16 +527,16 @@ item_in_popup(const char *saved_a_start, const char *saved_a_end, /* Returns the beginning of current day in seconds from 1900. */ long get_today(void) { - struct tm *lt; + struct tm lt; time_t current_time; long current_day; struct date day; current_time = time(NULL); - lt = localtime(¤t_time); - day.mm = lt->tm_mon + 1; - day.dd = lt->tm_mday; - day.yyyy = lt->tm_year + 1900; + localtime_r(¤t_time, <); + day.mm = lt.tm_mon + 1; + day.dd = lt.tm_mday; + day.yyyy = lt.tm_year + 1900; current_day = date2sec(day, 0, 0); return current_day; @@ -541,10 +550,12 @@ long now(void) char *nowstr(void) { + struct tm lt; static char buf[BUFSIZ]; time_t t = now(); - strftime(buf, sizeof buf, "%a %b %d %T %Y", localtime(&t)); + localtime_r(&t, <); + strftime(buf, sizeof buf, "%a %b %d %T %Y", <); return buf; } @@ -1183,15 +1194,17 @@ static void print_date(long date, long day, const char *extformat) printf("%ld", date); else { time_t t = date; - struct tm *lt = localtime((time_t *) & t); + struct tm lt; + + localtime_r((time_t *)&t, <); if (extformat[0] == '\0' || !strcmp(extformat, "default")) { if (date >= day && date <= day + DAYINSEC) - strftime(buf, BUFSIZ, "%H:%M", lt); + strftime(buf, BUFSIZ, "%H:%M", <); else - strftime(buf, BUFSIZ, "..:..", lt); + strftime(buf, BUFSIZ, "..:..", <); } else { - strftime(buf, BUFSIZ, extformat, lt); + strftime(buf, BUFSIZ, extformat, <); } printf("%s", buf); -- cgit v1.2.3-54-g00ecf