diff options
| author | sebres <sebres@users.sourceforge.net> | 2025-07-21 18:21:43 (GMT) |
|---|---|---|
| committer | sebres <sebres@users.sourceforge.net> | 2025-07-21 18:21:43 (GMT) |
| commit | e7e759c639a63a5b4ef2bcce0a9aaab4cb1ffe10 (patch) | |
| tree | fd8fdc0c2f22981d9fed6e2e98447134f1341112 | |
| parent | 6f2c08cfba0904f3bbd9f983e04381b4e86fccee (diff) | |
| download | tcl-e7e759c639a63a5b4ef2bcce0a9aaab4cb1ffe10.zip tcl-e7e759c639a63a5b4ef2bcce0a9aaab4cb1ffe10.tar.gz tcl-e7e759c639a63a5b4ef2bcce0a9aaab4cb1ffe10.tar.bz2 | |
amend to [61c01e0edb08a9ed], more cases for increment ref-count with use-after-free prevention for interim normalized path object; provide fixes minimally invasive (if API used with fresh created path object, so decrement would not destroy it if normalized path equal original given path)
| -rw-r--r-- | generic/tclIOUtil.c | 2 | ||||
| -rw-r--r-- | win/tclWinFCmd.c | 13 | ||||
| -rw-r--r-- | win/tclWinFile.c | 25 |
3 files changed, 31 insertions, 9 deletions
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index a124406..7e9c0f0 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -2996,6 +2996,7 @@ Tcl_FSChdir( Tcl_SetErrno(ENOENT); return -1; } + if (normDirName != pathPtr) { Tcl_IncrRefCount(normDirName); } if (fsPtr == &tclNativeFilesystem) { /* @@ -3029,6 +3030,7 @@ Tcl_FSChdir( } else { FsUpdateCwd(normDirName, NULL); } + if (normDirName != pathPtr) { Tcl_DecrRefCount(normDirName); } } return retVal; diff --git a/win/tclWinFCmd.c b/win/tclWinFCmd.c index 441337e..a9de366 100644 --- a/win/tclWinFCmd.c +++ b/win/tclWinFCmd.c @@ -910,10 +910,16 @@ TclpObjCopyDirectory( int ret; normSrcPtr = Tcl_FSGetNormalizedPath(NULL,srcPathPtr); + if (normSrcPtr == NULL) { + return TCL_ERROR; + } + if (normSrcPtr != srcPathPtr) { Tcl_IncrRefCount(normSrcPtr); } normDestPtr = Tcl_FSGetNormalizedPath(NULL,destPathPtr); - if ((normSrcPtr == NULL) || (normDestPtr == NULL)) { + if (normDestPtr == NULL) { + if (normSrcPtr != srcPathPtr) { Tcl_DecrRefCount(normSrcPtr); } return TCL_ERROR; } + if (normDestPtr != destPathPtr) { Tcl_IncrRefCount(normDestPtr); } Tcl_WinUtfToTChar(Tcl_GetString(normSrcPtr), -1, &srcString); Tcl_WinUtfToTChar(Tcl_GetString(normDestPtr), -1, &dstString); @@ -934,6 +940,9 @@ TclpObjCopyDirectory( Tcl_DStringFree(&ds); Tcl_IncrRefCount(*errorPtr); } + + if (normSrcPtr != srcPathPtr) { Tcl_DecrRefCount(normSrcPtr); } + if (normDestPtr != destPathPtr) { Tcl_DecrRefCount(normDestPtr); } return ret; } @@ -988,6 +997,7 @@ TclpObjRemoveDirectory( if (normPtr == NULL) { return TCL_ERROR; } + if (normPtr != pathPtr) { Tcl_IncrRefCount(normPtr); } Tcl_WinUtfToTChar(Tcl_GetString(normPtr), -1, &native); ret = DoRemoveDirectory(&native, recursive, &ds); Tcl_DStringFree(&native); @@ -1008,6 +1018,7 @@ TclpObjRemoveDirectory( } Tcl_DStringFree(&ds); } + if (normPtr && normPtr != pathPtr) { Tcl_DecrRefCount(normPtr); } return ret; } diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 6ddb9d0..73776ee 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -915,19 +915,23 @@ TclpMatchInDirectory( int len; DWORD attr; - const char *str = Tcl_GetStringFromObj(norm,&len); + const char *str; + if (norm != pathPtr) { Tcl_IncrRefCount(norm); } + str = TclGetStringFromObj(norm, &len); native = (const TCHAR *) Tcl_FSGetNativePath(pathPtr); if (tclWinProcs->getFileAttributesExProc == NULL) { attr = (*tclWinProcs->getFileAttributesProc)(native); if (attr == 0xffffffff) { + if (norm != pathPtr) { Tcl_DecrRefCount(norm); } return TCL_OK; } } else { WIN32_FILE_ATTRIBUTE_DATA data; if ((*tclWinProcs->getFileAttributesExProc)(native, GetFileExInfoStandard, &data) != TRUE) { + if (norm != pathPtr) { Tcl_DecrRefCount(norm); } return TCL_OK; } attr = data.dwFileAttributes; @@ -936,6 +940,7 @@ TclpMatchInDirectory( if (NativeMatchType(WinIsDrive(str,len), attr, native, types)) { Tcl_ListObjAppendElement(interp, resultPtr, pathPtr); } + if (norm != pathPtr) { Tcl_DecrRefCount(norm); } } return TCL_OK; } else { @@ -961,7 +966,8 @@ TclpMatchInDirectory( if (fileNamePtr == NULL) { return TCL_ERROR; } - Tcl_IncrRefCount(fileNamePtr); /* ensure it'd be alive, while used. */ + /* Ensure it'd be alive, while used. */ + if (fileNamePtr != pathPtr) { Tcl_IncrRefCount(fileNamePtr); } /* * Verify that the specified path exists and is actually a directory. @@ -969,13 +975,13 @@ TclpMatchInDirectory( native = Tcl_FSGetNativePath(pathPtr); if (native == NULL) { - Tcl_DecrRefCount(fileNamePtr); + if (fileNamePtr != pathPtr) { Tcl_DecrRefCount(fileNamePtr); } return TCL_OK; } attr = (*tclWinProcs->getFileAttributesProc)(native); if ((attr == 0xffffffff) || ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0)) { - Tcl_DecrRefCount(fileNamePtr); + if (fileNamePtr != pathPtr) { Tcl_DecrRefCount(fileNamePtr); } return TCL_OK; } @@ -993,7 +999,7 @@ TclpMatchInDirectory( Tcl_DStringAppend(&dsOrig, "/", 1); dirLength++; } - Tcl_DecrRefCount(fileNamePtr); + if (fileNamePtr != pathPtr) { Tcl_DecrRefCount(fileNamePtr); } dirName = Tcl_DStringValue(&dsOrig); /* @@ -2487,18 +2493,21 @@ TclpObjLink( int res; TCHAR *LinkTarget; TCHAR *LinkSource = (TCHAR *) Tcl_FSGetNativePath(pathPtr); - Tcl_Obj *normalizedToPtr = Tcl_FSGetNormalizedPath(NULL, toPtr); + Tcl_Obj *normToPtr = Tcl_FSGetNormalizedPath(NULL, toPtr); - if (normalizedToPtr == NULL) { + if (normToPtr == NULL) { return NULL; } + if (normToPtr != toPtr) { Tcl_IncrRefCount(normToPtr); } - LinkTarget = (TCHAR *) Tcl_FSGetNativePath(normalizedToPtr); + LinkTarget = (TCHAR *) Tcl_FSGetNativePath(normToPtr); if (LinkSource == NULL || LinkTarget == NULL) { + if (normToPtr != toPtr) { Tcl_DecrRefCount(normToPtr); } return NULL; } res = WinLink(LinkSource, LinkTarget, linkAction); + if (normToPtr != toPtr) { Tcl_DecrRefCount(normToPtr); } if (res == 0) { return toPtr; } else { |
