diff --git a/src/onion/response.c b/src/onion/response.c index eaaf3cae..6cfbb9e1 100644 --- a/src/onion/response.c +++ b/src/onion/response.c @@ -49,7 +49,7 @@ const char *onion_response_code_description(int code); #ifndef DONT_USE_DATE_HEADER static volatile time_t onion_response_last_time = 0; -static char *onion_response_last_date_header = NULL; +static char onion_response_last_date_header[128] = { 0 }; #ifdef HAVE_PTHREADS pthread_rwlock_t onion_response_date_lock = PTHREAD_RWLOCK_INITIALIZER; #endif @@ -101,26 +101,33 @@ onion_response *onion_response_new(onion_request * req) { if (t != current) { ONION_DEBUG("Recalculating date header"); - char current_datetime[200]; + char current_datetime[sizeof(onion_response_last_date_header)]; if (localtime_r(&t, &tmp) == NULL) { perror("localtime"); exit(EXIT_FAILURE); } - if (strftime - (current_datetime, sizeof(current_datetime), - "%a, %d %b %Y %H:%M:%S %Z", &tmp) == 0) { + size_t len_current_datetime = strftime( + current_datetime, sizeof(current_datetime), + "%a, %d %b %Y %H:%M:%S %Z", &tmp); + if ( len_current_datetime == 0) { fprintf(stderr, "strftime returned 0"); exit(EXIT_FAILURE); } #ifdef HAVE_PTHREADS pthread_rwlock_wrlock(&onion_response_date_lock); #endif - __sync_bool_compare_and_swap(&onion_response_last_time, current, t); - if (onion_response_last_date_header) - onion_low_free(onion_response_last_date_header); - onion_response_last_date_header = onion_low_strdup(current_datetime); + if ( __sync_bool_compare_and_swap(&onion_response_last_time, current, t)){ + /* First thread with new timestamp updates date_header. + * 'current_datetime' of other threads will be ignored. + * (… and except very rare conditions, it is the + * same string in all threads.) + */ + assert(len_current_datetime < sizeof(onion_response_last_date_header)); + memcpy(onion_response_last_date_header, + current_datetime, len_current_datetime); + } #ifdef HAVE_PTHREADS pthread_rwlock_unlock(&onion_response_date_lock); #endif @@ -129,7 +136,7 @@ onion_response *onion_response_new(onion_request * req) { #ifdef HAVE_PTHREADS pthread_rwlock_rdlock(&onion_response_date_lock); #endif - assert(onion_response_last_date_header); + assert(onion_response_last_date_header[0]); onion_dict_add(res->headers, "Date", onion_response_last_date_header, OD_DUP_VALUE); #ifdef HAVE_PTHREADS