Skip to content

Commit 9720d23

Browse files
rscharfegitster
authored andcommitted
date: make DATE_MODE thread-safe
date_mode_from_type() modifies a static variable and returns a pointer to it. This is not thread-safe. Most callers of date_mode_from_type() use it via the macro DATE_MODE and pass its result on to functions like show_date(), which take a const pointer and don't modify the struct. Avoid the static storage by putting the variable on the stack and returning the whole struct date_mode. Change functions that take a constant pointer to expect the whole struct instead. Reduce the cost of passing struct date_mode around on 64-bit systems by reordering its members to close the hole between the 32-bit wide .type and the 64-bit aligned .strftime_fmt as well as the alignment hole at the end. sizeof reports 24 before and 16 with this change on x64. Keep .type at the top to still allow initialization without designator -- though that's only done in a single location, in builtin/blame.c. Signed-off-by: René Scharfe <[email protected]> Acked-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1f49f75 commit 9720d23

File tree

12 files changed

+44
-44
lines changed

12 files changed

+44
-44
lines changed

builtin/blame.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ static const char *format_time(timestamp_t time, const char *tz_str,
316316
size_t time_width;
317317
int tz;
318318
tz = atoi(tz_str);
319-
time_str = show_date(time, tz, &blame_date_mode);
319+
time_str = show_date(time, tz, blame_date_mode);
320320
strbuf_addstr(&time_buf, time_str);
321321
/*
322322
* Add space paddings to time_buf to display a fixed width
@@ -1029,7 +1029,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
10291029
blame_date_width = sizeof("Thu Oct 19 16:00:04 2006 -0700");
10301030
break;
10311031
case DATE_STRFTIME:
1032-
blame_date_width = strlen(show_date(0, 0, &blame_date_mode)) + 1; /* add the null */
1032+
blame_date_width = strlen(show_date(0, 0, blame_date_mode)) + 1; /* add the null */
10331033
break;
10341034
}
10351035
blame_date_width -= 1; /* strip the null */

date.c

+18-18
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,13 @@ void show_date_relative(timestamp_t time, struct strbuf *timebuf)
207207
(diff + 183) / 365);
208208
}
209209

210-
struct date_mode *date_mode_from_type(enum date_mode_type type)
210+
struct date_mode date_mode_from_type(enum date_mode_type type)
211211
{
212-
static struct date_mode mode = DATE_MODE_INIT;
212+
struct date_mode mode = DATE_MODE_INIT;
213213
if (type == DATE_STRFTIME)
214214
BUG("cannot create anonymous strftime date_mode struct");
215215
mode.type = type;
216-
return &mode;
216+
return mode;
217217
}
218218

219219
static void show_date_normal(struct strbuf *buf, timestamp_t time, struct tm *tm, int tz, struct tm *human_tm, int human_tz, int local)
@@ -283,21 +283,21 @@ static void show_date_normal(struct strbuf *buf, timestamp_t time, struct tm *tm
283283
strbuf_addf(buf, " %+05d", tz);
284284
}
285285

286-
const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
286+
const char *show_date(timestamp_t time, int tz, struct date_mode mode)
287287
{
288288
struct tm *tm;
289289
struct tm tmbuf = { 0 };
290290
struct tm human_tm = { 0 };
291291
int human_tz = -1;
292292
static struct strbuf timebuf = STRBUF_INIT;
293293

294-
if (mode->type == DATE_UNIX) {
294+
if (mode.type == DATE_UNIX) {
295295
strbuf_reset(&timebuf);
296296
strbuf_addf(&timebuf, "%"PRItime, time);
297297
return timebuf.buf;
298298
}
299299

300-
if (mode->type == DATE_HUMAN) {
300+
if (mode.type == DATE_HUMAN) {
301301
struct timeval now;
302302

303303
get_time(&now);
@@ -306,22 +306,22 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
306306
human_tz = local_time_tzoffset(now.tv_sec, &human_tm);
307307
}
308308

309-
if (mode->local)
309+
if (mode.local)
310310
tz = local_tzoffset(time);
311311

312-
if (mode->type == DATE_RAW) {
312+
if (mode.type == DATE_RAW) {
313313
strbuf_reset(&timebuf);
314314
strbuf_addf(&timebuf, "%"PRItime" %+05d", time, tz);
315315
return timebuf.buf;
316316
}
317317

318-
if (mode->type == DATE_RELATIVE) {
318+
if (mode.type == DATE_RELATIVE) {
319319
strbuf_reset(&timebuf);
320320
show_date_relative(time, &timebuf);
321321
return timebuf.buf;
322322
}
323323

324-
if (mode->local)
324+
if (mode.local)
325325
tm = time_to_tm_local(time, &tmbuf);
326326
else
327327
tm = time_to_tm(time, tz, &tmbuf);
@@ -331,17 +331,17 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
331331
}
332332

333333
strbuf_reset(&timebuf);
334-
if (mode->type == DATE_SHORT)
334+
if (mode.type == DATE_SHORT)
335335
strbuf_addf(&timebuf, "%04d-%02d-%02d", tm->tm_year + 1900,
336336
tm->tm_mon + 1, tm->tm_mday);
337-
else if (mode->type == DATE_ISO8601)
337+
else if (mode.type == DATE_ISO8601)
338338
strbuf_addf(&timebuf, "%04d-%02d-%02d %02d:%02d:%02d %+05d",
339339
tm->tm_year + 1900,
340340
tm->tm_mon + 1,
341341
tm->tm_mday,
342342
tm->tm_hour, tm->tm_min, tm->tm_sec,
343343
tz);
344-
else if (mode->type == DATE_ISO8601_STRICT) {
344+
else if (mode.type == DATE_ISO8601_STRICT) {
345345
strbuf_addf(&timebuf, "%04d-%02d-%02dT%02d:%02d:%02d",
346346
tm->tm_year + 1900,
347347
tm->tm_mon + 1,
@@ -354,16 +354,16 @@ const char *show_date(timestamp_t time, int tz, const struct date_mode *mode)
354354
tz = abs(tz);
355355
strbuf_addf(&timebuf, "%02d:%02d", tz / 100, tz % 100);
356356
}
357-
} else if (mode->type == DATE_RFC2822)
357+
} else if (mode.type == DATE_RFC2822)
358358
strbuf_addf(&timebuf, "%.3s, %d %.3s %d %02d:%02d:%02d %+05d",
359359
weekday_names[tm->tm_wday], tm->tm_mday,
360360
month_names[tm->tm_mon], tm->tm_year + 1900,
361361
tm->tm_hour, tm->tm_min, tm->tm_sec, tz);
362-
else if (mode->type == DATE_STRFTIME)
363-
strbuf_addftime(&timebuf, mode->strftime_fmt, tm, tz,
364-
!mode->local);
362+
else if (mode.type == DATE_STRFTIME)
363+
strbuf_addftime(&timebuf, mode.strftime_fmt, tm, tz,
364+
!mode.local);
365365
else
366-
show_date_normal(&timebuf, time, tm, tz, &human_tm, human_tz, mode->local);
366+
show_date_normal(&timebuf, time, tm, tz, &human_tm, human_tz, mode.local);
367367
return timebuf.buf;
368368
}
369369

date.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ enum date_mode_type {
2222

2323
struct date_mode {
2424
enum date_mode_type type;
25-
const char *strftime_fmt;
2625
int local;
26+
const char *strftime_fmt;
2727
};
2828

2929
#define DATE_MODE_INIT { \
@@ -36,14 +36,14 @@ struct date_mode {
3636
* show_date(t, tz, DATE_MODE(NORMAL));
3737
*/
3838
#define DATE_MODE(t) date_mode_from_type(DATE_##t)
39-
struct date_mode *date_mode_from_type(enum date_mode_type type);
39+
struct date_mode date_mode_from_type(enum date_mode_type type);
4040

4141
/**
4242
* Format <'time', 'timezone'> into static memory according to 'mode'
4343
* and return it. The mode is an initialized "struct date_mode"
4444
* (usually from the DATE_MODE() macro).
4545
*/
46-
const char *show_date(timestamp_t time, int timezone, const struct date_mode *mode);
46+
const char *show_date(timestamp_t time, int timezone, struct date_mode mode);
4747

4848
/**
4949
* Parse a date format for later use with show_date().

gpg-interface.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ static int verify_ssh_signed_buffer(struct signature_check *sigc,
483483

484484
if (sigc->payload_timestamp)
485485
strbuf_addf(&verify_time, "-Overify-time=%s",
486-
show_date(sigc->payload_timestamp, 0, &verify_date_mode));
486+
show_date(sigc->payload_timestamp, 0, verify_date_mode));
487487

488488
/* Find the principal from the signers */
489489
strvec_pushl(&ssh_keygen.args, fmt->program,

log-tree.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ void show_log(struct rev_info *opt)
777777
*/
778778
show_reflog_message(opt->reflog_info,
779779
opt->commit_format == CMIT_FMT_ONELINE,
780-
&opt->date_mode,
780+
opt->date_mode,
781781
opt->date_mode_explicit);
782782
if (opt->commit_format == CMIT_FMT_ONELINE)
783783
return;

oss-fuzz/fuzz-date.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
1111
int16_t tz;
1212
timestamp_t ts;
1313
enum date_mode_type dmtype;
14-
struct date_mode *dm;
14+
struct date_mode dm;
1515

1616
if (size <= 4)
1717
/*
@@ -40,10 +40,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
4040
free(str);
4141

4242
dm = date_mode_from_type(dmtype);
43-
dm->local = local;
43+
dm.local = local;
4444
show_date(ts, (int)tz, dm);
4545

46-
date_mode_release(dm);
46+
date_mode_release(&dm);
4747

4848
return 0;
4949
}

pretty.c

+9-9
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
428428
}
429429

430430
const char *show_ident_date(const struct ident_split *ident,
431-
const struct date_mode *mode)
431+
struct date_mode mode)
432432
{
433433
timestamp_t date = 0;
434434
long tz = 0;
@@ -592,7 +592,7 @@ void pp_user_info(struct pretty_print_context *pp,
592592
switch (pp->fmt) {
593593
case CMIT_FMT_MEDIUM:
594594
strbuf_addf(sb, "Date: %s\n",
595-
show_ident_date(&ident, &pp->date_mode));
595+
show_ident_date(&ident, pp->date_mode));
596596
break;
597597
case CMIT_FMT_EMAIL:
598598
case CMIT_FMT_MBOXRD:
@@ -601,7 +601,7 @@ void pp_user_info(struct pretty_print_context *pp,
601601
break;
602602
case CMIT_FMT_FULLER:
603603
strbuf_addf(sb, "%sDate: %s\n", what,
604-
show_ident_date(&ident, &pp->date_mode));
604+
show_ident_date(&ident, pp->date_mode));
605605
break;
606606
default:
607607
/* notin' */
@@ -775,7 +775,7 @@ static int mailmap_name(const char **email, size_t *email_len,
775775

776776
static size_t format_person_part(struct strbuf *sb, char part,
777777
const char *msg, int len,
778-
const struct date_mode *dmode)
778+
struct date_mode dmode)
779779
{
780780
/* currently all placeholders have same length */
781781
const int placeholder_len = 2;
@@ -1034,7 +1034,7 @@ static void rewrap_message_tail(struct strbuf *sb,
10341034
static int format_reflog_person(struct strbuf *sb,
10351035
char part,
10361036
struct reflog_walk_info *log,
1037-
const struct date_mode *dmode)
1037+
struct date_mode dmode)
10381038
{
10391039
const char *ident;
10401040

@@ -1602,7 +1602,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
16021602
if (c->pretty_ctx->reflog_info)
16031603
get_reflog_selector(sb,
16041604
c->pretty_ctx->reflog_info,
1605-
&c->pretty_ctx->date_mode,
1605+
c->pretty_ctx->date_mode,
16061606
c->pretty_ctx->date_mode_explicit,
16071607
(placeholder[1] == 'd'));
16081608
return 2;
@@ -1617,7 +1617,7 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
16171617
return format_reflog_person(sb,
16181618
placeholder[1],
16191619
c->pretty_ctx->reflog_info,
1620-
&c->pretty_ctx->date_mode);
1620+
c->pretty_ctx->date_mode);
16211621
}
16221622
return 0; /* unknown %g placeholder */
16231623
case 'N':
@@ -1712,11 +1712,11 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
17121712
case 'a': /* author ... */
17131713
return format_person_part(sb, placeholder[1],
17141714
msg + c->author.off, c->author.len,
1715-
&c->pretty_ctx->date_mode);
1715+
c->pretty_ctx->date_mode);
17161716
case 'c': /* committer ... */
17171717
return format_person_part(sb, placeholder[1],
17181718
msg + c->committer.off, c->committer.len,
1719-
&c->pretty_ctx->date_mode);
1719+
c->pretty_ctx->date_mode);
17201720
case 'e': /* encoding */
17211721
if (c->commit_encoding)
17221722
strbuf_addstr(sb, c->commit_encoding);

pretty.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ int format_set_trailers_options(struct process_trailer_options *opts,
168168
* a well-known sentinel date if they appear bogus.
169169
*/
170170
const char *show_ident_date(const struct ident_split *id,
171-
const struct date_mode *mode);
171+
struct date_mode mode);
172172

173173

174174
#endif /* PRETTY_H */

ref-filter.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1627,7 +1627,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
16271627
tz = strtol(zone, NULL, 10);
16281628
if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE)
16291629
goto bad;
1630-
v->s = xstrdup(show_date(timestamp, tz, &date_mode));
1630+
v->s = xstrdup(show_date(timestamp, tz, date_mode));
16311631
v->value = timestamp;
16321632
date_mode_release(&date_mode);
16331633
return;

reflog-walk.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
223223

224224
void get_reflog_selector(struct strbuf *sb,
225225
struct reflog_walk_info *reflog_info,
226-
const struct date_mode *dmode, int force_date,
226+
struct date_mode dmode, int force_date,
227227
int shorten)
228228
{
229229
struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
@@ -297,7 +297,7 @@ timestamp_t get_reflog_timestamp(struct reflog_walk_info *reflog_info)
297297
}
298298

299299
void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
300-
const struct date_mode *dmode, int force_date)
300+
struct date_mode dmode, int force_date)
301301
{
302302
if (reflog_info && reflog_info->last_commit_reflog) {
303303
struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;

reflog-walk.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ void reflog_walk_info_release(struct reflog_walk_info *info);
1010
int add_reflog_for_walk(struct reflog_walk_info *info,
1111
struct commit *commit, const char *name);
1212
void show_reflog_message(struct reflog_walk_info *info, int,
13-
const struct date_mode *, int force_date);
13+
struct date_mode, int force_date);
1414
void get_reflog_message(struct strbuf *sb,
1515
struct reflog_walk_info *reflog_info);
1616
const char *get_reflog_ident(struct reflog_walk_info *reflog_info);
1717
timestamp_t get_reflog_timestamp(struct reflog_walk_info *reflog_info);
1818
void get_reflog_selector(struct strbuf *sb,
1919
struct reflog_walk_info *reflog_info,
20-
const struct date_mode *dmode, int force_date,
20+
struct date_mode dmode, int force_date,
2121
int shorten);
2222

2323
int reflog_walk_empty(struct reflog_walk_info *walk);

t/helper/test-date.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static void show_dates(const char **argv, const char *format)
5252
arg++;
5353
tz = atoi(arg);
5454

55-
printf("%s -> %s\n", *argv, show_date(t, tz, &mode));
55+
printf("%s -> %s\n", *argv, show_date(t, tz, mode));
5656
}
5757

5858
date_mode_release(&mode);

0 commit comments

Comments
 (0)