summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2025-07-21 18:21:43 (GMT)
committersebres <sebres@users.sourceforge.net>2025-07-21 18:21:43 (GMT)
commite7e759c639a63a5b4ef2bcce0a9aaab4cb1ffe10 (patch)
treefd8fdc0c2f22981d9fed6e2e98447134f1341112
parent6f2c08cfba0904f3bbd9f983e04381b4e86fccee (diff)
downloadtcl-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.c2
-rw-r--r--win/tclWinFCmd.c13
-rw-r--r--win/tclWinFile.c25
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 {