diff options
author | dgp <dgp@users.sourceforge.net> | 2019-09-11 16:10:10 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2019-09-11 16:10:10 (GMT) |
commit | 2975cfd58997a8336ac32e85422216ed9401d657 (patch) | |
tree | c078503fce991f7fd87af85cc7ab334174acf820 /generic | |
parent | 6f8793bff8c23d618a040b4098b714eef9e33d19 (diff) | |
parent | c2f8b74ee565c5ebeb9a4d320ddcd8922dbf020b (diff) | |
download | tcl-2975cfd58997a8336ac32e85422216ed9401d657.zip tcl-2975cfd58997a8336ac32e85422216ed9401d657.tar.gz tcl-2975cfd58997a8336ac32e85422216ed9401d657.tar.bz2 |
merge 8.7
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tcl.h | 2 | ||||
-rw-r--r-- | generic/tclBasic.c | 14 | ||||
-rw-r--r-- | generic/tclCompile.c | 47 | ||||
-rw-r--r-- | generic/tclDictObj.c | 2 | ||||
-rw-r--r-- | generic/tclInterp.c | 8 | ||||
-rw-r--r-- | generic/tclProc.c | 18 |
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); |