git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
@ 2011-11-19 13:45 Vincent van Ravesteijn
  2011-11-19 13:52 ` [PATCH 2/2] MSVC: Use _putenv instead of putenv " Vincent van Ravesteijn
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Vincent van Ravesteijn @ 2011-11-19 13:45 UTC (permalink / raw)
  To: git
  Cc: msysgit, gitster, kusmabite, Johannes.Schindelin,
	Vincent van Ravesteijn

When compiled with MSVC, git crashes on Windows when calling
fstat(stdout) when stdout is closed. fstat is being called at the end of
run_builtin and this will thus be a problem for builtin command that close
stdout. This happens for 'format-patch' which closes stdout after a call to
freopen which directs stdout to the format patch file.

To prevent the crash and to prevent git from writing cruft into the patch
file, we do not close stdout, but redirect it to "nul" instead.

Signed-off-by: Vincent van Ravesteijn <vfr@lyx.org>
---
 compat/mingw.c |    8 ++++++++
 compat/mingw.h |    3 +++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index efdc703..8943df5 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -319,6 +319,14 @@ ssize_t mingw_write(int fd, const void *buf, size_t count)
 	return write(fd, buf, min(count, 31 * 1024 * 1024));
 }
 
+#undef fclose
+int mingw_fclose (FILE *stream)
+{
+	if (fileno(stream) == 1 && freopen("nul", "w", stream))
+		return 0;
+	return fclose(stream);
+}
+
 #undef fopen
 FILE *mingw_fopen (const char *filename, const char *otype)
 {
diff --git a/compat/mingw.h b/compat/mingw.h
index ff18401..80a6015 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -179,6 +179,9 @@ int mingw_open (const char *filename, int oflags, ...);
 ssize_t mingw_write(int fd, const void *buf, size_t count);
 #define write mingw_write
 
+int mingw_fclose(FILE *stream);
+#define fclose mingw_fclose
+
 FILE *mingw_fopen (const char *filename, const char *otype);
 #define fopen mingw_fopen
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/2] MSVC: Use _putenv instead of putenv to prevent a crash
  2011-11-19 13:45 [PATCH 1/2] MSVC: Do not close stdout to prevent a crash Vincent van Ravesteijn
@ 2011-11-19 13:52 ` Vincent van Ravesteijn
  2011-11-19 14:41 ` [PATCH 1/2] MSVC: Do not close stdout " Andreas Schwab
  2011-11-19 20:11 ` [msysGit] " Johannes Sixt
  2 siblings, 0 replies; 14+ messages in thread
From: Vincent van Ravesteijn @ 2011-11-19 13:52 UTC (permalink / raw)
  To: git
  Cc: msysgit, gitster, kusmabite, Johannes.Schindelin,
	Vincent van Ravesteijn

Git crashes when trying to clear a nonexistent environment variable using
the putenv function. The crash occurs when freeing the option string. In
debug mode the assert "CrtIsValidHeapPointer" fails.

Using _putenv instead of putenv makes the crash and assert disappear.

Signed-off-by: Vincent van Ravesteijn <vfr@lyx.org>
---
The strange thing is that all over the internet people are claiming
that there is no difference between putenv and _putenv. Still, using
_putenv fixes the crash for me. 

If there is someone around who is more knowledgeable in this area,
please comment.

 compat/setenv.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/compat/setenv.c b/compat/setenv.c
index 3a22ea7..b23937d 100644
--- a/compat/setenv.c
+++ b/compat/setenv.c
@@ -23,7 +23,7 @@ int gitsetenv(const char *name, const char *value, int replace)
 	memcpy(envstr + namelen + 1, value, valuelen);
 	envstr[namelen + valuelen + 1] = 0;
 
-	out = putenv(envstr);
+	out = _putenv(envstr);
 	/* putenv(3) makes the argument string part of the environment,
 	 * and changing that string modifies the environment --- which
 	 * means we do not own that storage anymore.  Do not free
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-19 13:45 [PATCH 1/2] MSVC: Do not close stdout to prevent a crash Vincent van Ravesteijn
  2011-11-19 13:52 ` [PATCH 2/2] MSVC: Use _putenv instead of putenv " Vincent van Ravesteijn
@ 2011-11-19 14:41 ` Andreas Schwab
  2011-11-19 19:11   ` Junio C Hamano
  2011-11-19 20:11 ` [msysGit] " Johannes Sixt
  2 siblings, 1 reply; 14+ messages in thread
From: Andreas Schwab @ 2011-11-19 14:41 UTC (permalink / raw)
  To: Vincent van Ravesteijn
  Cc: git, msysgit, gitster, kusmabite, Johannes.Schindelin

Vincent van Ravesteijn <vfr@lyx.org> writes:

> When compiled with MSVC, git crashes on Windows when calling
> fstat(stdout) when stdout is closed. fstat is being called at the end of

ITYM fileno(stdout).

> run_builtin and this will thus be a problem for builtin command that close
> stdout. This happens for 'format-patch' which closes stdout after a call to
> freopen which directs stdout to the format patch file.

It shouldn't do that in the first place.  This is an error on any
platform.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-19 14:41 ` [PATCH 1/2] MSVC: Do not close stdout " Andreas Schwab
@ 2011-11-19 19:11   ` Junio C Hamano
  2011-11-19 20:16     ` Andreas Schwab
  2011-11-19 20:52     ` Vincent van Ravesteijn
  0 siblings, 2 replies; 14+ messages in thread
From: Junio C Hamano @ 2011-11-19 19:11 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Vincent van Ravesteijn, git, msysgit, gitster, kusmabite,
	Johannes.Schindelin

Andreas Schwab <schwab@linux-m68k.org> writes:

> Vincent van Ravesteijn <vfr@lyx.org> writes:
>
>> When compiled with MSVC, git crashes on Windows when calling
>> fstat(stdout) when stdout is closed. fstat is being called at the end of
>
> ITYM fileno(stdout).
> 
>> run_builtin and this will thus be a problem for builtin command that close
>> stdout. This happens for 'format-patch' which closes stdout after a call to
>> freopen which directs stdout to the format patch file.
>
> It shouldn't do that in the first place.  This is an error on any
> platform.

Correct. The clean-up codepath is for built-in command implementations
that write out their result and return 0 to signal success. If we let the
crt0 to run its usual clean-ups like closing the standard output stream,
we wouldn't be able to catch errors from there.

For built-ins that perform their own clean-ups, it is their responsibility
to be careful, hence we skip this part of the code.

We have relied on fstat(-1, &st) to correctly error out, and if MSVC build
crashes, it is a bug in its fstat() emulation, I would think.

We could do something like the following patch to be extra defensive,
though.

 git.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/git.c b/git.c
index 8e34903..64c28e4 100644
--- a/git.c
+++ b/git.c
@@ -309,8 +309,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 	if (status)
 		return status;
 
-	/* Somebody closed stdout? */
-	if (fstat(fileno(stdout), &st))
+	if (fileno(stdout) < 0 || /* Somebody closed stdout? */
+	    fstat(fileno(stdout), &st))
 		return 0;
 	/* Ignore write errors for pipes and sockets.. */
 	if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode))

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [msysGit] [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-19 13:45 [PATCH 1/2] MSVC: Do not close stdout to prevent a crash Vincent van Ravesteijn
  2011-11-19 13:52 ` [PATCH 2/2] MSVC: Use _putenv instead of putenv " Vincent van Ravesteijn
  2011-11-19 14:41 ` [PATCH 1/2] MSVC: Do not close stdout " Andreas Schwab
@ 2011-11-19 20:11 ` Johannes Sixt
  2011-11-22  6:45   ` Vincent van Ravesteijn
  2 siblings, 1 reply; 14+ messages in thread
From: Johannes Sixt @ 2011-11-19 20:11 UTC (permalink / raw)
  To: Vincent van Ravesteijn
  Cc: git, msysgit, gitster, kusmabite, Johannes.Schindelin

Am 19.11.2011 14:45, schrieb Vincent van Ravesteijn:
> When compiled with MSVC, git crashes on Windows when calling
> fstat(stdout) when stdout is closed. fstat is being called at the end of
> run_builtin and this will thus be a problem for builtin command that close
> stdout. This happens for 'format-patch' which closes stdout after a call to
> freopen which directs stdout to the format patch file.

This crash happens because of the some drainbramage in the MS's newer C
runtime: Its functions never return EINVAL (like fstat should in this
case), but it is assumed that cases where EINVAL should be returned are
programming errors, and the application is redirected, via an "invalid
agument handler" to abort() instead. (It is advertized as a security
feature.)

> To prevent the crash and to prevent git from writing cruft into the patch
> file, we do not close stdout, but redirect it to "nul" instead.

A more robust solution is to add invalidcontinue.obj to the linker
command line. This installs an invalid argument handler that does not
abort, and restores a sane behavior.

-- Hannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-19 19:11   ` Junio C Hamano
@ 2011-11-19 20:16     ` Andreas Schwab
  2011-11-20  3:27       ` Junio C Hamano
  2011-11-19 20:52     ` Vincent van Ravesteijn
  1 sibling, 1 reply; 14+ messages in thread
From: Andreas Schwab @ 2011-11-19 20:16 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Vincent van Ravesteijn, git, msysgit, kusmabite,
	Johannes.Schindelin

Junio C Hamano <gitster@pobox.com> writes:

> We have relied on fstat(-1, &st) to correctly error out, and if MSVC build
> crashes, it is a bug in its fstat() emulation, I would think.

fileno(stdout) is alread wrong if stdout was closed.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-19 19:11   ` Junio C Hamano
  2011-11-19 20:16     ` Andreas Schwab
@ 2011-11-19 20:52     ` Vincent van Ravesteijn
  1 sibling, 0 replies; 14+ messages in thread
From: Vincent van Ravesteijn @ 2011-11-19 20:52 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Andreas Schwab, git, msysgit, kusmabite, Johannes.Schindelin

Op 19-11-2011 20:11, Junio C Hamano schreef:
> ... This happens for 'format-patch' which closes stdout after a call to
> freopen which directs stdout to the format patch file.
>> It shouldn't do that in the first place.  This is an error on any
>> platform.
> Correct. The clean-up codepath is for built-in command implementations
> that write out their result and return 0 to signal success. If we let the
> crt0 to run its usual clean-ups like closing the standard output stream,
> we wouldn't be able to catch errors from there.
>
> For built-ins that perform their own clean-ups, it is their responsibility
> to be careful, hence we skip this part of the code.
>
> We have relied on fstat(-1,&st) to correctly error out, and if MSVC build
> crashes, it is a bug in its fstat() emulation, I would think.

This doesn't work because fileno(stdout) returns 1 no matter whether we 
closed stdout or not.

My reasoning for the proposed patch is that we call freopen(..., stdout) 
for each patch file to write, but we only call fclose(stdout) once. Sp, 
I concluded that it is not necessary to close stdout and that we just 
need to redirect any new output to stdout.

Vincent

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-19 20:16     ` Andreas Schwab
@ 2011-11-20  3:27       ` Junio C Hamano
  2011-11-20  9:05         ` Andreas Schwab
  2011-11-20  9:27         ` [msysGit] " Johannes Sixt
  0 siblings, 2 replies; 14+ messages in thread
From: Junio C Hamano @ 2011-11-20  3:27 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Vincent van Ravesteijn, git, msysgit, kusmabite,
	Johannes.Schindelin

Andreas Schwab <schwab@linux-m68k.org> writes:

> Junio C Hamano <gitster@pobox.com> writes:
>
>> We have relied on fstat(-1, &st) to correctly error out, and if MSVC build
>> crashes, it is a bug in its fstat() emulation, I would think.
>
> fileno(stdout) is alread wrong if stdout was closed.

The "-1" in my message comes from here:

    DESCRIPTION

    The fileno() function shall return the integer file descriptor
    associated with the stream pointed to by stream.

    RETURN VALUE

    Upon successful completion, fileno() shall return the integer value of
    the file descriptor associated with stream. Otherwise, the value -1
    shall be returned and errno set to indicate the error.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-20  3:27       ` Junio C Hamano
@ 2011-11-20  9:05         ` Andreas Schwab
  2011-11-20  9:27         ` [msysGit] " Johannes Sixt
  1 sibling, 0 replies; 14+ messages in thread
From: Andreas Schwab @ 2011-11-20  9:05 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Vincent van Ravesteijn, git, msysgit, kusmabite,
	Johannes.Schindelin

Junio C Hamano <gitster@pobox.com> writes:

> Andreas Schwab <schwab@linux-m68k.org> writes:
>
>> Junio C Hamano <gitster@pobox.com> writes:
>>
>>> We have relied on fstat(-1, &st) to correctly error out, and if MSVC build
>>> crashes, it is a bug in its fstat() emulation, I would think.
>>
>> fileno(stdout) is alread wrong if stdout was closed.
>
> The "-1" in my message comes from here:
>
>     DESCRIPTION
>
>     The fileno() function shall return the integer file descriptor
>     associated with the stream pointed to by stream.

After fclose(stdout) the stream does not exist any more.  Thus the use
of fileno(stdout) is undefined, in fact *any* use of stdout is undefined
afterwards.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [msysGit] Re: [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-20  3:27       ` Junio C Hamano
  2011-11-20  9:05         ` Andreas Schwab
@ 2011-11-20  9:27         ` Johannes Sixt
  2011-11-20 21:10           ` Junio C Hamano
  1 sibling, 1 reply; 14+ messages in thread
From: Johannes Sixt @ 2011-11-20  9:27 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Andreas Schwab, Vincent van Ravesteijn, git, msysgit, kusmabite,
	Johannes.Schindelin

Am 20.11.2011 04:27, schrieb Junio C Hamano:
> Andreas Schwab <schwab@linux-m68k.org> writes:
> 
>> Junio C Hamano <gitster@pobox.com> writes:
>>
>>> We have relied on fstat(-1, &st) to correctly error out, and if MSVC build
>>> crashes, it is a bug in its fstat() emulation, I would think.
>>
>> fileno(stdout) is alread wrong if stdout was closed.
> 
> The "-1" in my message comes from here:
> 
>     DESCRIPTION
> 
>     The fileno() function shall return the integer file descriptor
>     associated with the stream pointed to by stream.
> 
>     RETURN VALUE
> 
>     Upon successful completion, fileno() shall return the integer value of
>     the file descriptor associated with stream. Otherwise, the value -1
>     shall be returned and errno set to indicate the error.

But in the description of fclose() there is also:

  After the call to fclose(), any use of stream results in undefined
  behavior.

And we do call fclose(stdout) in cmd_format_patch.

-- Hannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [msysGit] Re: [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-20  9:27         ` [msysGit] " Johannes Sixt
@ 2011-11-20 21:10           ` Junio C Hamano
  0 siblings, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2011-11-20 21:10 UTC (permalink / raw)
  To: Johannes Sixt
  Cc: Andreas Schwab, Vincent van Ravesteijn, git, msysgit, kusmabite,
	Johannes.Schindelin

Johannes Sixt <j6t@kdbg.org> writes:

> But in the description of fclose() there is also:
>
>   After the call to fclose(), any use of stream results in undefined
>   behavior.
>
> And we do call fclose(stdout) in cmd_format_patch.

Yeah; this means the "in case builtin implementation is too lazy to clean
up after themselves, run_builtin() will clean things up for them" approach
taken by 0f15731 (Check for IO errors after running a command, 2007-06-24)
fundamentally does not work, which is a bit sad.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [msysGit] [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-19 20:11 ` [msysGit] " Johannes Sixt
@ 2011-11-22  6:45   ` Vincent van Ravesteijn
  2011-11-22 20:24     ` Johannes Sixt
  0 siblings, 1 reply; 14+ messages in thread
From: Vincent van Ravesteijn @ 2011-11-22  6:45 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git, msysgit, gitster, kusmabite, Johannes.Schindelin



>> To prevent the crash and to prevent git from writing cruft into the patch
>> file, we do not close stdout, but redirect it to "nul" instead.
> A more robust solution is to add invalidcontinue.obj to the linker
> command line. This installs an invalid argument handler that does not
> abort, and restores a sane behavior.

This seems to work only for release builds or did I miss something ?

Is there any argument to not redirect stdout to "/dev/null" on all 
platforms ?

Vincent

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [msysGit] [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-22  6:45   ` Vincent van Ravesteijn
@ 2011-11-22 20:24     ` Johannes Sixt
  2011-11-22 21:27       ` Vincent van Ravesteijn
  0 siblings, 1 reply; 14+ messages in thread
From: Johannes Sixt @ 2011-11-22 20:24 UTC (permalink / raw)
  To: Vincent van Ravesteijn
  Cc: git, msysgit, gitster, kusmabite, Johannes.Schindelin

Am 22.11.2011 07:45, schrieb Vincent van Ravesteijn:
>>> To prevent the crash and to prevent git from writing cruft into the
>>> patch
>>> file, we do not close stdout, but redirect it to "nul" instead.
>> A more robust solution is to add invalidcontinue.obj to the linker
>> command line. This installs an invalid argument handler that does not
>> abort, and restores a sane behavior.
> 
> This seems to work only for release builds or did I miss something ?

I cannot tell, but I would be surprised if that were the case. I didn't
test with debug builds (only our 'make MSVC=1' build). A cursory look at
the CRT source code does not show anything that would be different
between a debug and a release build regarding invalidcontinue.obj.

> Is there any argument to not redirect stdout to "/dev/null" on all
> platforms ?

You paper over a crack in the wall. You hide a bug.

-- Hannes

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [msysGit] [PATCH 1/2] MSVC: Do not close stdout to prevent a crash
  2011-11-22 20:24     ` Johannes Sixt
@ 2011-11-22 21:27       ` Vincent van Ravesteijn
  0 siblings, 0 replies; 14+ messages in thread
From: Vincent van Ravesteijn @ 2011-11-22 21:27 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git, msysgit, gitster, kusmabite, Johannes.Schindelin


>> Is there any argument to not redirect stdout to "/dev/null" on all
>> platforms ?
> You paper over a crack in the wall. You hide a bug.

Luckily I'm still trying to find the crack and not ready to tape 
anything yet.

Vincent

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2011-11-22 21:27 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-19 13:45 [PATCH 1/2] MSVC: Do not close stdout to prevent a crash Vincent van Ravesteijn
2011-11-19 13:52 ` [PATCH 2/2] MSVC: Use _putenv instead of putenv " Vincent van Ravesteijn
2011-11-19 14:41 ` [PATCH 1/2] MSVC: Do not close stdout " Andreas Schwab
2011-11-19 19:11   ` Junio C Hamano
2011-11-19 20:16     ` Andreas Schwab
2011-11-20  3:27       ` Junio C Hamano
2011-11-20  9:05         ` Andreas Schwab
2011-11-20  9:27         ` [msysGit] " Johannes Sixt
2011-11-20 21:10           ` Junio C Hamano
2011-11-19 20:52     ` Vincent van Ravesteijn
2011-11-19 20:11 ` [msysGit] " Johannes Sixt
2011-11-22  6:45   ` Vincent van Ravesteijn
2011-11-22 20:24     ` Johannes Sixt
2011-11-22 21:27       ` Vincent van Ravesteijn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).