From 03df1c4fdcf3eba690c937f14950f18d6817dc51 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 3 Dec 2008 09:51:45 +0000 Subject: Fix [Bug 2380318] --- ChangeLog | 16 ++++++++++------ win/tclWinPipe.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b4f6cb..9d5a363 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,13 @@ +2008-12-03 Donal K. Fellows + + * win/tclWinPipe.c (TclpOpenTemporaryFile): Avoid an infinite loop due + to GetTempFileName/CreateFile interaction. [Bug 2380318] + 2008-12-03 Don Porter - * generic/tclFileName.c (DoGlob): One of the - Tcl_FSMatchInDirectory() calls did not have its return code checked. - This caused error messages returned by some Tcl_Filesystem drivers - to be swallowed. + * generic/tclFileName.c (DoGlob): One of the Tcl_FSMatchInDirectory + calls did not have its return code checked. This caused error messages + returned by some Tcl_Filesystem drivers to be swallowed. 2008-12-02 Don Porter @@ -30,8 +34,8 @@ 2008-12-02 Andreas Kupries * generic/tclIO.c (TclFinalizeIOSubsystem): Replaced Alexandre - Ferrieux's first patch for [Bug 2270477] with a gentler version, - also supplied by him. + Ferrieux's first patch for [Bug 2270477] with a gentler version, also + supplied by him. 2008-12-01 Don Porter diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c index ad9e6d8..10caad7 100644 --- a/win/tclWinPipe.c +++ b/win/tclWinPipe.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclWinPipe.c,v 1.68 2008/11/29 18:17:20 dkf Exp $ + * RCS: @(#) $Id: tclWinPipe.c,v 1.69 2008/12/03 09:51:45 dkf Exp $ */ #include "tclWinInt.h" @@ -3175,26 +3175,66 @@ TclpOpenTemporaryFile( Tcl_Obj *resultingNameObj) { WCHAR name[MAX_PATH]; + char *namePtr; HANDLE handle; DWORD flags = FILE_ATTRIBUTE_TEMPORARY; + int length, counter, counter2; + Tcl_DString buf; if (!resultingNameObj) { flags |= FILE_FLAG_DELETE_ON_CLOSE; } + namePtr = (char *) name; + length = tclWinProcs->getTempPathProc(MAX_PATH, name); + if (length == 0) { + goto gotError; + } + if (tclWinProcs->useWide) { + namePtr += length * sizeof(WCHAR); + } else { + namePtr += length; + } + if (basenameObj) { + const char *string = Tcl_GetStringFromObj(basenameObj, &length); + + Tcl_WinUtfToTChar(string, length, &buf); + memcpy(namePtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf)); + namePtr += Tcl_DStringLength(&buf); + Tcl_DStringFree(&buf); + } else { + TCHAR *baseStr = tclWinProcs->useWide ? + (TCHAR *) L"TCL" : (TCHAR *) "TCL"; + int length = tclWinProcs->useWide ? 3*sizeof(WCHAR) : 3; + + memcpy(namePtr, baseStr, length); + namePtr += length; + } + counter = TclpGetClicks() % 65533; + counter2 = 1024; /* Only try this many times! Prevents + * an infinite loop. */ + do { - if (TempFileName(name) == 0) { - TclWinConvertError(GetLastError()); - return NULL; + char number[TCL_INTEGER_SPACE + 4]; + + sprintf(number, "%d.TMP", counter); + counter = (unsigned short) (counter + 1); + Tcl_WinUtfToTChar(number, strlen(number), &buf); + memcpy(namePtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf)); + if (tclWinProcs->useWide) { + *(WCHAR *)(namePtr + Tcl_DStringLength(&buf) + 1) = '\0'; + } else { + namePtr[Tcl_DStringLength(&buf) + 1] = '\0'; } + Tcl_DStringFree(&buf); handle = tclWinProcs->createFileProc((TCHAR *) name, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, flags, NULL); } while (handle == INVALID_HANDLE_VALUE + && --counter2 > 0 && GetLastError() == ERROR_FILE_EXISTS); if (handle == INVALID_HANDLE_VALUE) { - TclWinConvertError(GetLastError()); - return NULL; + goto gotError; } if (resultingNameObj) { @@ -3206,6 +3246,10 @@ TclpOpenTemporaryFile( return Tcl_MakeFileChannel((ClientData) handle, TCL_READABLE|TCL_WRITABLE); + + gotError: + TclWinConvertError(GetLastError()); + return NULL; } /* -- cgit v0.12