summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2019-09-11 16:10:10 (GMT)
committerdgp <dgp@users.sourceforge.net>2019-09-11 16:10:10 (GMT)
commit2975cfd58997a8336ac32e85422216ed9401d657 (patch)
treec078503fce991f7fd87af85cc7ab334174acf820 /generic
parent6f8793bff8c23d618a040b4098b714eef9e33d19 (diff)
parentc2f8b74ee565c5ebeb9a4d320ddcd8922dbf020b (diff)
downloadtcl-2975cfd58997a8336ac32e85422216ed9401d657.zip
tcl-2975cfd58997a8336ac32e85422216ed9401d657.tar.gz
tcl-2975cfd58997a8336ac32e85422216ed9401d657.tar.bz2
merge 8.7
Diffstat (limited to 'generic')
-rw-r--r--generic/tcl.h2
-rw-r--r--generic/tclBasic.c14
-rw-r--r--generic/tclCompile.c47
-rw-r--r--generic/tclDictObj.c2
-rw-r--r--generic/tclInterp.c8
-rw-r--r--generic/tclProc.c18
6 files changed, 51 insertions, 40 deletions
diff --git a/generic/tcl.h b/generic/tcl.h
index 2997dac..4d37f93 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -406,7 +406,7 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
#if defined(_WIN32)
# ifdef __BORLANDC__
typedef struct stati64 Tcl_StatBuf;
-# elif defined(_WIN64) || defined(__MINGW_USE_VC2005_COMPAT) || defined(_USE_64BIT_TIME_T)
+# elif defined(_WIN64) || defined(_USE_64BIT_TIME_T)
typedef struct __stat64 Tcl_StatBuf;
# elif (defined(_MSC_VER) && (_MSC_VER < 1400)) || defined(_USE_32BIT_TIME_T)
typedef struct _stati64 Tcl_StatBuf;
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index f7bfa14..db1e526 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -657,19 +657,13 @@ Tcl_CreateInterp(void)
Tcl_Panic("Tcl_CallFrame must not be smaller than CallFrame");
}
-#if defined(_WIN32) && !defined(_WIN64) && !defined(_USE_64BIT_TIME_T) \
- && !defined(__MINGW_USE_VC2005_COMPAT)
- /* If Tcl is compiled on Win32 using -D_USE_64BIT_TIME_T or
- * -D__MINGW_USE_VC2005_COMPAT, the result is a binary incompatible
- * with the 'standard' build of Tcl: All extensions using Tcl_StatBuf
- * or interal functions like TclpGetDate() need to be recompiled in
+#if defined(_WIN32) && !defined(_WIN64) && !defined(_USE_64BIT_TIME_T)
+ /* If Tcl is compiled on Win32 using -D_USE_64BIT_TIME_T
+ * the result is a binary incompatible with the 'standard' build of
+ * Tcl: All extensions using Tcl_StatBuf need to be recompiled in
* the same way. Therefore, this is not officially supported.
* In stead, it is recommended to use Win64 or Tcl 9.0 (not released yet)
*/
- if (sizeof(time_t) != 4) {
- /*NOTREACHED*/
- Tcl_Panic("<time.h> is not compatible with MSVC");
- }
if ((offsetof(Tcl_StatBuf,st_atime) != 32)
|| (offsetof(Tcl_StatBuf,st_ctime) != 40)) {
/*NOTREACHED*/
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 8a13eba..122e1b3 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -2166,18 +2166,26 @@ TclCompileScript(
/* Each iteration compiles one command from the script. */
- while (numBytes > 0) {
- Tcl_Parse parse;
+ if (numBytes > 0) {
+ /*
+ * Don't use system stack (size of Tcl_Parse is ca. 400 bytes), so
+ * many nested compilations (body enclosed in body) can cause abnormal
+ * program termination with a stack overflow exception, bug [fec0c17d39].
+ */
+ Tcl_Parse *parsePtr = ckalloc(sizeof(Tcl_Parse));
+
+ do {
const char *next;
- if (TCL_OK != Tcl_ParseCommand(interp, p, numBytes, 0, &parse)) {
+ if (TCL_OK != Tcl_ParseCommand(interp, p, numBytes, 0, parsePtr)) {
/*
- * Compile bytecodes to report the parse error at runtime.
+ * Compile bytecodes to report the parsePtr error at runtime.
*/
- Tcl_LogCommandInfo(interp, script, parse.commandStart,
- parse.term + 1 - parse.commandStart);
+ Tcl_LogCommandInfo(interp, script, parsePtr->commandStart,
+ parsePtr->term + 1 - parsePtr->commandStart);
TclCompileSyntaxError(interp, envPtr);
+ ckfree(parsePtr);
return;
}
@@ -2188,9 +2196,9 @@ TclCompileScript(
*/
if ((tclTraceCompile >= 1) && (envPtr->procPtr == NULL)) {
- int commandLength = parse.term - parse.commandStart;
+ int commandLength = parsePtr->term - parsePtr->commandStart;
fprintf(stdout, " Compiling: ");
- TclPrintSource(stdout, parse.commandStart,
+ TclPrintSource(stdout, parsePtr->commandStart,
TclMin(commandLength, 55));
fprintf(stdout, "\n");
}
@@ -2201,48 +2209,51 @@ TclCompileScript(
* (See test info-30.33).
*/
- TclAdvanceLines(&envPtr->line, p, parse.commandStart);
+ TclAdvanceLines(&envPtr->line, p, parsePtr->commandStart);
TclAdvanceContinuations(&envPtr->line, &envPtr->clNext,
- parse.commandStart - envPtr->source);
+ parsePtr->commandStart - envPtr->source);
/*
* Advance parser to the next command in the script.
*/
- next = parse.commandStart + parse.commandSize;
+ next = parsePtr->commandStart + parsePtr->commandSize;
numBytes -= next - p;
p = next;
- if (parse.numWords == 0) {
+ if (parsePtr->numWords == 0) {
/*
* The "command" parsed has no words. In this case we can skip
* the rest of the loop body. With no words, clearly
* CompileCommandTokens() has nothing to do. Since the parser
* aggressively sucks up leading comment and white space,
- * including newlines, parse.commandStart must be pointing at
+ * including newlines, parsePtr->commandStart must be pointing at
* either the end of script, or a command-terminating semi-colon.
* In either case, the TclAdvance*() calls have nothing to do.
* Finally, when no words are parsed, no tokens have been
- * allocated at parse.tokenPtr so there's also nothing for
+ * allocated at parsePtr->tokenPtr so there's also nothing for
* Tcl_FreeParse() to do.
*
* The advantage of this shortcut is that CompileCommandTokens()
- * can be written with an assumption that parse.numWords > 0, with
+ * can be written with an assumption that parsePtr->numWords > 0, with
* the implication the CCT() always generates bytecode.
*/
continue;
}
- lastCmdIdx = CompileCommandTokens(interp, &parse, envPtr);
+ lastCmdIdx = CompileCommandTokens(interp, parsePtr, envPtr);
/*
* TIP #280: Track lines in the just compiled command.
*/
- TclAdvanceLines(&envPtr->line, parse.commandStart, p);
+ TclAdvanceLines(&envPtr->line, parsePtr->commandStart, p);
TclAdvanceContinuations(&envPtr->line, &envPtr->clNext,
p - envPtr->source);
- Tcl_FreeParse(&parse);
+ Tcl_FreeParse(parsePtr);
+ } while (numBytes > 0);
+
+ ckfree(parsePtr);
}
if (lastCmdIdx == -1) {
diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c
index 1952778..083af70 100644
--- a/generic/tclDictObj.c
+++ b/generic/tclDictObj.c
@@ -3310,7 +3310,7 @@ DictUpdateCmd(
}
if (objPtr == NULL) {
/* ??? */
- Tcl_UnsetVar(interp, Tcl_GetString(objv[i+1]), 0);
+ Tcl_UnsetVar2(interp, Tcl_GetString(objv[i+1]), NULL, 0);
} else if (Tcl_ObjSetVar2(interp, objv[i+1], NULL, objPtr,
TCL_LEAVE_ERR_MSG) == NULL) {
TclDecrRefCount(dictPtr);
diff --git a/generic/tclInterp.c b/generic/tclInterp.c
index 3188fce..bd786f3 100644
--- a/generic/tclInterp.c
+++ b/generic/tclInterp.c
@@ -3291,7 +3291,7 @@ Tcl_MakeSafe(
* No env array in a safe slave.
*/
- Tcl_UnsetVar(interp, "env", TCL_GLOBAL_ONLY);
+ Tcl_UnsetVar2(interp, "env", NULL, TCL_GLOBAL_ONLY);
/*
* Remove unsafe parts of tcl_platform
@@ -3307,9 +3307,9 @@ Tcl_MakeSafe(
* nameofexecutable])
*/
- Tcl_UnsetVar(interp, "tclDefaultLibrary", TCL_GLOBAL_ONLY);
- Tcl_UnsetVar(interp, "tcl_library", TCL_GLOBAL_ONLY);
- Tcl_UnsetVar(interp, "tcl_pkgPath", TCL_GLOBAL_ONLY);
+ Tcl_UnsetVar2(interp, "tclDefaultLibrary", NULL, TCL_GLOBAL_ONLY);
+ Tcl_UnsetVar2(interp, "tcl_library", NULL, TCL_GLOBAL_ONLY);
+ Tcl_UnsetVar2(interp, "tcl_pkgPath", NULL, TCL_GLOBAL_ONLY);
/*
* Remove the standard channels from the interpreter; safe interpreters do
diff --git a/generic/tclProc.c b/generic/tclProc.c
index 8beb701..85d6531 100644
--- a/generic/tclProc.c
+++ b/generic/tclProc.c
@@ -808,7 +808,7 @@ TclObjGetFrame(
} else {
result = -1;
}
- } else if (TclGetWideBitsFromObj(interp, objPtr, &w) == TCL_OK) {
+ } else if (TclGetWideBitsFromObj(NULL, objPtr, &w) == TCL_OK) {
/*
* If this were an integer, we'd have succeeded already.
* Docs say we have to treat this as a 'bad level' error.
@@ -817,10 +817,16 @@ TclObjGetFrame(
}
}
- if (result == 0) {
- level = curLevel - 1;
- }
if (result != -1) {
+ /* if relative current level */
+ if (result == 0) {
+ if (!curLevel) {
+ /* we are in top-level, so simply generate bad level */
+ name = "1";
+ goto badLevel;
+ }
+ level = curLevel - 1;
+ }
if (level >= 0) {
CallFrame *framePtr;
for (framePtr = iPtr->varFramePtr; framePtr != NULL;
@@ -832,9 +838,9 @@ TclObjGetFrame(
}
}
}
-
+badLevel:
if (name == NULL) {
- name = TclGetString(objPtr);
+ name = objPtr ? TclGetString(objPtr) : "1" ;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad level \"%s\"", name));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LEVEL", name, NULL);