Skip to content

Commit

Permalink
mingw: abort on invalid strftime formats
Browse files Browse the repository at this point in the history
On Windows, strftime() does not silently ignore invalid formats, but
warns about them and then returns 0 and sets errno to EINVAL.

Unfortunately, Git does not expect such a behavior, as it disagrees
with strftime()'s semantics on Linux. As a consequence, Git
misinterprets the return value 0 as "I need more space" and grows the
buffer. As the larger buffer does not fix the format, the buffer grows
and grows and grows until we are out of memory and abort.

Ideally, we would switch off the parameter validation just for
strftime(), but we cannot even override the invalid parameter handler
via _set_thread_local_invalid_parameter_handler() using MINGW because
that function is not declared. Even _set_invalid_parameter_handler(),
which *is* declared, does not help, as it simply does... nothing.

So let's just bite the bullet and override strftime() for MINGW and
abort on an invalid format string. While this does not provide the
best user experience, it is the best we can do.

See https://msdn.microsoft.com/en-us/library/fe06s4ak.aspx for more
details.

This fixes #863

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Nov 3, 2017
1 parent b997864 commit eacb15f
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 0 deletions.
11 changes: 11 additions & 0 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,17 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
return rc;
}

#undef strftime
size_t mingw_strftime(char *s, size_t max,
const char *format, const struct tm *tm)
{
size_t ret = strftime(s, max, format, tm);

if (!ret && errno == EINVAL)
die("invalid strftime format: '%s'", format);
return ret;
}

unsigned int sleep (unsigned int seconds)
{
Sleep(seconds*1000);
Expand Down
3 changes: 3 additions & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,9 @@ int mingw_fstat(int fd, struct stat *buf);

int mingw_utime(const char *file_name, const struct utimbuf *times);
#define utime mingw_utime
size_t mingw_strftime(char *s, size_t max,
const char *format, const struct tm *tm);
#define strftime mingw_strftime

pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
const char *dir,
Expand Down

0 comments on commit eacb15f

Please sign in to comment.