summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/exec.n39
-rw-r--r--generic/tcl.h5
-rw-r--r--generic/tclBasic.c21
-rw-r--r--generic/tclCmdAH.c9
-rw-r--r--generic/tclDate.c6
-rw-r--r--generic/tclDecls.h14
-rw-r--r--generic/tclEncoding.c73
-rw-r--r--generic/tclFileName.c4
-rw-r--r--generic/tclGetDate.y4
-rw-r--r--generic/tclIO.c19
-rw-r--r--generic/tclInt.h13
-rw-r--r--generic/tclInterp.c9
-rw-r--r--generic/tclNamesp.c4
-rw-r--r--generic/tclTest.c2
-rw-r--r--generic/tclZipfs.c119
-rw-r--r--tests/io.test84
-rw-r--r--unix/Makefile.in2
-rw-r--r--unix/tclAppInit.c2
-rw-r--r--win/tclAppInit.c2
19 files changed, 256 insertions, 175 deletions
diff --git a/doc/exec.n b/doc/exec.n
index 3cfc29d..01df48b 100644
--- a/doc/exec.n
+++ b/doc/exec.n
@@ -234,6 +234,45 @@ processor (\fBcmd.exe /c\fR), because this causes truncation of command-line
(also the argument chain) on the first newline character.
But it works properly with an executable (using CommandLineToArgv, etc).
.PP
+\fBArgument quoting\fR
+.RS
+The arguments of the \fBexec\fR command are mapped to the arguments of the called
+program. Additional quote characters (\fB"\fR) are automatically added around
+arguments if expected. Special characters are escaped by inserting backslash
+characters.
+.PP
+The MS-Windows environment does execute programs mentioned in the arguments and
+called batch files (conspec) replace environment variables, which may have side
+effects (vulnerabilities) or break any already existing quoting (for example,
+if the environment variable contains a special character like a \fB"\fR).
+Examples are:
+.CS
+% exec my-echo.cmd {test&whoami}
+ test
+ mylogin
+% exec my-echo.cmd "ENV X:%X%"
+ ENV X: CONTENT OF X
+.CE
+The following formatting is automatically performed on any
+argument item:
+.IP \(bu 3
+Avoid subprogram execution:
+Any special character argument containing a special character (\fB&\fR, \fB|\fR,
+\fB^\fR, \fB<\fR, \fB>\fR, \fB!\fR, \fB(\fR, \fB)\fR, \fB(\fR, \fB%\fR)
+is automatically enclosed in quotes (\fB"\fR). Any data quote is escaped by
+insertion of backslash characters.
+.IP \(bu 3
+Avoid environment variable replacement:
+Any appearence of environment variable reference (\fB%\fR) is individually quoted
+by \fB"\fR.
+.PP
+TCL 8.6.10 refined this quoting by adding quoting for data quotes and individual
+quoting of "\fB%\fR".
+This may break present scripts which rely on the replacement functionality of
+environment variables.
+A solution with command parameters is envisaged for a future release of TCL.
+.RE
+.PP
The Tk console text widget does not provide real standard IO capabilities.
Under Tk, when redirecting from standard input, all applications will see an
immediate end-of-file; information redirected to standard output or standard
diff --git a/generic/tcl.h b/generic/tcl.h
index 2f1f793..5769cbd 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -2180,10 +2180,9 @@ typedef struct Tcl_EncodingType {
* changes, ensure ENCODING_PROFILE_* macros in tclInt.h are modified if
* necessary.
*/
+#define TCL_ENCODING_PROFILE_STRICT TCL_ENCODING_STOPONERROR
#define TCL_ENCODING_PROFILE_TCL8 0x01000000
-#define TCL_ENCODING_PROFILE_STRICT 0x02000000
-#define TCL_ENCODING_PROFILE_REPLACE 0x03000000
-#define TCL_ENCODING_PROFILE_DEFAULT TCL_ENCODING_PROFILE_TCL8
+#define TCL_ENCODING_PROFILE_REPLACE 0x02000000
/*
* The following definitions are the error codes returned by the conversion
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 0120466..b01717e 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -1082,14 +1082,9 @@ Tcl_CreateInterp(void)
iPtr->deferredCallbacks = NULL;
/*
- * Create the core commands. Do it here, rather than calling
- * Tcl_CreateCommand, because it's faster (there's no need to check for a
- * preexisting command by the same name). If a command has a Tcl_CmdProc
- * but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to
- * TclInvokeStringCommand. This is an object-based wrapper function that
- * extracts strings, calls the string function, and creates an object for
- * the result. Similarly, if a command has a Tcl_ObjCmdProc but no
- * Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.
+ * Create the core commands. Do it here, rather than calling Tcl_CreateObjCommand,
+ * because it's faster (there's no need to check for a preexisting command
+ * by the same name). Set the Tcl_CmdProc to TclInvokeObjectCommand.
*/
for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
@@ -3140,7 +3135,7 @@ TclRenameCommand(
/*
* Make sure that the destination command does not already exist. The
* rename operation is like creating a command, so we should automatically
- * create the containing namespaces just like Tcl_CreateCommand would.
+ * create the containing namespaces just like Tcl_CreateObjCommand would.
*/
TclGetNamespaceForQualName(interp, newName, NULL,
@@ -3445,7 +3440,7 @@ Tcl_GetCommandInfoFromToken(
*
* Tcl_GetCommandName --
*
- * Given a token returned by Tcl_CreateCommand, this function returns the
+ * Given a token returned by Tcl_CreateObjCommand, this function returns the
* current name of the command (which may have changed due to renaming).
*
* Results:
@@ -3461,7 +3456,7 @@ const char *
Tcl_GetCommandName(
TCL_UNUSED(Tcl_Interp *),
Tcl_Command command) /* Token for command returned by a previous
- * call to Tcl_CreateCommand. The command must
+ * call to Tcl_CreateObjCommand. The command must
* not have been deleted. */
{
Command *cmdPtr = (Command *) command;
@@ -3484,7 +3479,7 @@ Tcl_GetCommandName(
*
* Tcl_GetCommandFullName --
*
- * Given a token returned by, e.g., Tcl_CreateCommand or Tcl_FindCommand,
+ * Given a token returned by, e.g., Tcl_CreateObjCommand or Tcl_FindCommand,
* this function appends to an object the command's full name, qualified
* by a sequence of parent namespace names. The command's fully-qualified
* name may have changed due to renaming.
@@ -3503,7 +3498,7 @@ void
Tcl_GetCommandFullName(
Tcl_Interp *interp, /* Interpreter containing the command. */
Tcl_Command command, /* Token for command returned by a previous
- * call to Tcl_CreateCommand. The command must
+ * call to Tcl_CreateObjCommand. The command must
* not have been deleted. */
Tcl_Obj *objPtr) /* Points to the object onto which the
* command's full name is appended. */
diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c
index 12216d4..86f1cda 100644
--- a/generic/tclCmdAH.c
+++ b/generic/tclCmdAH.c
@@ -673,7 +673,7 @@ EncodingConvertfromObjCmd(
/*
* Convert the string into a byte array in 'ds'.
*/
-#if !defined(TCL_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9)
+#if !defined(TCL_NO_DEPRECATED)
if (ENCODING_PROFILE_GET(flags) == TCL_ENCODING_PROFILE_TCL8) {
/* Permits high bits to be non-0 in byte array (Tcl 8 style) */
bytesPtr = (char *) Tcl_GetByteArrayFromObj(data, &length);
@@ -865,11 +865,13 @@ EncodingDirsObjCmd(
return TCL_ERROR;
}
if (objc == 1) {
+fprintf(stdout, "ED GET CALLER\n"); fflush(stdout);
Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath());
return TCL_OK;
}
dirListObj = objv[1];
+fprintf(stdout, "ED SET CALLER\n"); fflush(stdout);
if (Tcl_SetEncodingSearchPath(dirListObj) == TCL_ERROR) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"expected directory list but got \"%s\"",
@@ -2212,7 +2214,7 @@ PathSplitCmd(
Tcl_WrongNumArgs(interp, 1, objv, "name");
return TCL_ERROR;
}
- res = Tcl_FSSplitPath(objv[1], NULL);
+ res = Tcl_FSSplitPath(objv[1], (Tcl_Size *)NULL);
if (res == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"could not read \"%s\": no such file or directory",
@@ -3109,7 +3111,8 @@ ForeachAssignments(
Tcl_Interp *interp,
struct ForeachState *statePtr)
{
- int i, v, k;
+ int i;
+ Tcl_Size v, k;
Tcl_Obj *valuePtr, *varValuePtr;
for (i=0 ; i<statePtr->numLists ; i++) {
diff --git a/generic/tclDate.c b/generic/tclDate.c
index 44d45f9..2f05753 100644
--- a/generic/tclDate.c
+++ b/generic/tclDate.c
@@ -64,7 +64,6 @@
#define yylex TclDatelex
#define yyerror TclDateerror
#define yydebug TclDatedebug
-#define yynerrs TclDatenerrs
/* Copy the first part of user declarations. */
@@ -1294,9 +1293,6 @@ static YYLTYPE yyloc_default
;
YYLTYPE yylloc = yyloc_default;
- /* Number of syntax errors so far. */
- int yynerrs;
-
int yystate;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
@@ -1360,7 +1356,6 @@ YYLTYPE yylloc = yyloc_default;
yystate = 0;
yyerrstatus = 0;
- yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
yylsp[0] = yylloc;
goto yysetstate;
@@ -2098,7 +2093,6 @@ yyerrlab:
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
- ++yynerrs;
#if ! YYERROR_VERBOSE
yyerror (&yylloc, info, YY_("syntax error"));
#else
diff --git a/generic/tclDecls.h b/generic/tclDecls.h
index 0fe582e..5768233 100644
--- a/generic/tclDecls.h
+++ b/generic/tclDecls.h
@@ -4331,23 +4331,29 @@ extern const TclStubs *tclStubsPtr;
#undef Tcl_GetIndexFromObjStruct
#undef Tcl_GetBooleanFromObj
#undef Tcl_GetBoolean
+#ifdef __GNUC__
+ /* If this gives: "error: size of array ‘_boolVar’ is negative", it means that sizeof(*boolPtr)>sizeof(int), which is not allowed */
+# define TCLBOOLWARNING(boolPtr) ({__attribute__((unused)) char _bool_Var[sizeof(*(boolPtr)) > sizeof(int) ? -1 : 1];}),
+#else
+# define TCLBOOLWARNING(boolPtr)
+#endif
#if defined(USE_TCL_STUBS)
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
(tclStubsPtr->tcl_GetIndexFromObjStruct((interp), (objPtr), (tablePtr), (offset), (msg), (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))
#define Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) \
- (sizeof(*(boolPtr)) == sizeof(int) ? tclStubsPtr->tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \
+ (sizeof(*(boolPtr)) >= sizeof(int) ? (TCLBOOLWARNING(boolPtr)tclStubsPtr->tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr))) : \
Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#define Tcl_GetBoolean(interp, src, boolPtr) \
- (sizeof(*(boolPtr)) == sizeof(int) ? tclStubsPtr->tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \
+ (sizeof(*(boolPtr)) >= sizeof(int) ? (TCLBOOLWARNING(boolPtr)tclStubsPtr->tcl_GetBoolean(interp, src, (int *)(boolPtr))) : \
Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#else
#define Tcl_GetIndexFromObjStruct(interp, objPtr, tablePtr, offset, msg, flags, indexPtr) \
((Tcl_GetIndexFromObjStruct)((interp), (objPtr), (tablePtr), (offset), (msg), (flags)|(int)(sizeof(*(indexPtr))<<1), (indexPtr)))
#define Tcl_GetBooleanFromObj(interp, objPtr, boolPtr) \
- (sizeof(*(boolPtr)) == sizeof(int) ? Tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \
+ (sizeof(*(boolPtr)) >= sizeof(int) ? (TCLBOOLWARNING(boolPtr)Tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr))) : \
Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#define Tcl_GetBoolean(interp, src, boolPtr) \
- (sizeof(*(boolPtr)) == sizeof(int) ? Tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \
+ (sizeof(*(boolPtr)) >= sizeof(int) ? (TCLBOOLWARNING(boolPtr)Tcl_GetBoolean(interp, src, (int *)(boolPtr))) : \
Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#endif
diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c
index b441bf63..ff73904 100644
--- a/generic/tclEncoding.c
+++ b/generic/tclEncoding.c
@@ -192,7 +192,7 @@ Tcl_Encoding tclUtf8Encoding = NULL;
* Names of encoding profiles and corresponding integer values.
* Keep alphabetical order for error messages.
*/
-static struct TclEncodingProfiles {
+static const struct TclEncodingProfiles {
const char *name;
int value;
} encodingProfiles[] = {
@@ -201,10 +201,10 @@ static struct TclEncodingProfiles {
{"tcl8", TCL_ENCODING_PROFILE_TCL8},
};
#define PROFILE_STRICT(flags_) \
- (ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_STRICT)
+ ((flags_) & TCL_ENCODING_PROFILE_STRICT)
#define PROFILE_REPLACE(flags_) \
- (ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_REPLACE)
+ ((ENCODING_PROFILE_GET(flags_) == TCL_ENCODING_PROFILE_REPLACE) && !PROFILE_STRICT(flags_))
#define UNICODE_REPLACE_CHAR ((Tcl_UniChar)0xFFFD)
#define SURROGATE(c_) (((c_) & ~0x7FF) == 0xD800)
@@ -439,6 +439,7 @@ FillEncodingFileMap(void)
Tcl_Size i, numDirs = 0;
Tcl_Obj *map, *searchPath;
+fprintf(stdout, "FEFM CALLER\n"); fflush(stdout);
searchPath = Tcl_GetEncodingSearchPath();
Tcl_IncrRefCount(searchPath);
TclListObjLengthM(NULL, searchPath, &numDirs);
@@ -722,6 +723,7 @@ Tcl_GetDefaultEncodingDir(void)
{
int numDirs;
Tcl_Obj *first, *searchPath = Tcl_GetEncodingSearchPath();
+fprintf(stdout, "GDE CALLER\n"); fflush(stdout);
TclListObjLengthM(NULL, searchPath, &numDirs);
if (numDirs == 0) {
@@ -758,6 +760,7 @@ Tcl_SetDefaultEncodingDir(
searchPath = Tcl_DuplicateObj(searchPath);
Tcl_ListObjReplace(NULL, searchPath, 0, 0, 1, &directory);
+fprintf(stdout, "SDE CALLER\n"); fflush(stdout);
Tcl_SetEncodingSearchPath(searchPath);
}
#endif
@@ -1183,10 +1186,6 @@ Tcl_ExternalToUtfDString(
* Possible flags values:
* target encoding. It should be composed by OR-ing the following:
* - *At most one* of TCL_ENCODING_PROFILE{DEFAULT,TCL8,STRICT}
- * - TCL_ENCODING_STOPONERROR: Backward compatibility. Sets the profile
- * to TCL_ENCODING_PROFILE_STRICT overriding any specified profile flags
- * Any other flag bits will cause an error to be returned (for future
- * compatibility)
*
* Results:
* The return value is one of
@@ -1489,8 +1488,6 @@ Tcl_UtfToExternalDString(
* the source buffer are invalid or cannot be represented in the
* target encoding. It should be composed by OR-ing the following:
* - *At most one* of TCL_ENCODING_PROFILE_*
- * - TCL_ENCODING_STOPONERROR: Backward compatibility. Sets the profile
- * to TCL_ENCODING_PROFILE_STRICT overriding any specified profile flags
*
* Results:
* The return value is one of
@@ -1778,6 +1775,7 @@ OpenEncodingFileChannel(
Tcl_Obj **dir, *path, *directory = NULL;
Tcl_Channel chan = NULL;
Tcl_Size i, numDirs;
+fprintf(stdout, "OEFC CALLER\n"); fflush(stdout);
TclListObjGetElementsM(NULL, searchPath, &numDirs, &dir);
Tcl_IncrRefCount(nameObj);
@@ -2413,7 +2411,6 @@ BinaryProc(
if (dstLen < 0) {
dstLen = 0;
}
- flags = TclEncodingSetProfileFlags(flags);
if ((flags & TCL_ENCODING_CHAR_LIMIT) && srcLen > *dstCharsPtr) {
srcLen = *dstCharsPtr;
}
@@ -2481,7 +2478,6 @@ UtfToUtfProc(
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
- flags = TclEncodingSetProfileFlags(flags);
if ((flags & TCL_ENCODING_END) == 0) {
srcClose -= 6;
}
@@ -2697,7 +2693,6 @@ Utf32ToUtfProc(
int result, numChars, charLimit = INT_MAX;
int ch = 0, bytesLeft = srcLen % 4;
- flags = TclEncodingSetProfileFlags(flags);
flags |= PTR2INT(clientData);
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
@@ -2854,7 +2849,6 @@ UtfToUtf32Proc(
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
- flags = TclEncodingSetProfileFlags(flags);
if ((flags & TCL_ENCODING_END) == 0) {
srcClose -= TCL_UTF_MAX;
}
@@ -2952,7 +2946,6 @@ Utf16ToUtfProc(
int result, numChars, charLimit = INT_MAX;
unsigned short ch = 0;
- flags = TclEncodingSetProfileFlags(flags);
flags |= PTR2INT(clientData);
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
@@ -3113,7 +3106,6 @@ UtfToUtf16Proc(
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
- flags = TclEncodingSetProfileFlags(flags);
if ((flags & TCL_ENCODING_END) == 0) {
srcClose -= TCL_UTF_MAX;
}
@@ -3219,7 +3211,6 @@ UtfToUcs2Proc(
int result, numChars, len;
Tcl_UniChar ch = 0;
- flags = TclEncodingSetProfileFlags(flags);
flags |= PTR2INT(clientData);
srcStart = src;
srcEnd = src + srcLen;
@@ -3329,7 +3320,6 @@ TableToUtfProc(
const unsigned short *pageZero;
TableEncodingData *dataPtr = (TableEncodingData *)clientData;
- flags = TclEncodingSetProfileFlags(flags);
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
@@ -3462,7 +3452,6 @@ TableFromUtfProc(
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
- flags = TclEncodingSetProfileFlags(flags);
if ((flags & TCL_ENCODING_END) == 0) {
srcClose -= TCL_UTF_MAX;
}
@@ -3563,7 +3552,6 @@ Iso88591ToUtfProc(
const char *dstEnd, *dstStart;
int result, numChars, charLimit = INT_MAX;
- flags = TclEncodingSetProfileFlags(flags);
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
@@ -3648,7 +3636,6 @@ Iso88591FromUtfProc(
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
- flags = TclEncodingSetProfileFlags(flags);
if ((flags & TCL_ENCODING_END) == 0) {
srcClose -= TCL_UTF_MAX;
}
@@ -3788,7 +3775,6 @@ EscapeToUtfProc(
int state, result, numChars, charLimit = INT_MAX;
const char *dstStart, *dstEnd;
- flags = TclEncodingSetProfileFlags(flags);
if (flags & TCL_ENCODING_CHAR_LIMIT) {
charLimit = *dstCharsPtr;
}
@@ -4010,7 +3996,6 @@ EscapeFromUtfProc(
srcStart = src;
srcEnd = src + srcLen;
srcClose = srcEnd;
- flags = TclEncodingSetProfileFlags(flags);
if ((flags & TCL_ENCODING_END) == 0) {
srcClose -= TCL_UTF_MAX;
}
@@ -4332,6 +4317,8 @@ InitializeEncodingSearchPath(
Tcl_Size i, numDirs, numBytes;
Tcl_Obj *libPathObj, *encodingObj, *searchPathObj;
+fprintf(stdout, "IESP\n"); fflush(stdout);
+
TclNewLiteralStringObj(encodingObj, "encoding");
TclNewObj(searchPathObj);
Tcl_IncrRefCount(encodingObj);
@@ -4459,48 +4446,6 @@ TclEncodingProfileIdToName(
/*
*------------------------------------------------------------------------
*
- * TclEncodingSetProfileFlags --
- *
- * Maps the flags supported in the encoding C API's to internal flags.
- *
- * For backward compatibility reasons, TCL_ENCODING_STOPONERROR is
- * is mapped to the TCL_ENCODING_PROFILE_STRICT overwriting any profile
- * specified.
- *
- * If no profile or an invalid profile is specified, it is set to
- * the default.
- *
- * Results:
- * Internal encoding flag mask.
- *
- * Side effects:
- * None.
- *
- *------------------------------------------------------------------------
- */
-int TclEncodingSetProfileFlags(int flags)
-{
- if (flags & TCL_ENCODING_STOPONERROR) {
- ENCODING_PROFILE_SET(flags, TCL_ENCODING_PROFILE_STRICT);
- } else {
- int profile = ENCODING_PROFILE_GET(flags);
- switch (profile) {
- case TCL_ENCODING_PROFILE_TCL8:
- case TCL_ENCODING_PROFILE_STRICT:
- case TCL_ENCODING_PROFILE_REPLACE:
- break;
- case 0: /* Unspecified by caller */
- default:
- ENCODING_PROFILE_SET(flags, TCL_ENCODING_PROFILE_TCL8);
- break;
- }
- }
- return flags;
-}
-
-/*
- *------------------------------------------------------------------------
- *
* TclGetEncodingProfiles --
*
* Get the list of supported encoding profiles.
diff --git a/generic/tclFileName.c b/generic/tclFileName.c
index 92d325f..7f4f1cc 100644
--- a/generic/tclFileName.c
+++ b/generic/tclFileName.c
@@ -2145,7 +2145,7 @@ DoGlob(
Tcl_GlobTypeData *types) /* List object containing list of acceptable
* types. May be NULL. */
{
- int baseLength, quoted, count;
+ int baseLength, quoted;
int result = TCL_OK;
char *name, *p, *openBrace, *closeBrace, *firstSpecialChar;
Tcl_Obj *joinedPtr;
@@ -2155,7 +2155,6 @@ DoGlob(
* past the last initial separator.
*/
- count = 0;
name = pattern;
for (; *pattern != '\0'; pattern++) {
if (*pattern == '\\') {
@@ -2175,7 +2174,6 @@ DoGlob(
} else if (strchr(separators, *pattern) == NULL) {
break;
}
- count++;
}
/*
diff --git a/generic/tclGetDate.y b/generic/tclGetDate.y
index 13daef2..5a79cf2 100644
--- a/generic/tclGetDate.y
+++ b/generic/tclGetDate.y
@@ -641,7 +641,7 @@ static const TABLE TimezoneTable[] = {
{ "ist", tZONE, -HOUR(11/2) }, /* Indian Standard */
{ "zp6", tZONE, -HOUR( 6) }, /* USSR Zone 5 */
#if 0
- /* For completeness. NST is also Newfoundland Stanard, nad SST is
+ /* For completeness. NST is also Newfoundland Standard, and SST is
* also Swedish Summer. */
{ "nst", tZONE, -HOUR(13/2) }, /* North Sumatra */
{ "sst", tZONE, -HOUR( 7) }, /* South Sumatra, USSR Zone 6 */
@@ -1099,7 +1099,7 @@ TclClockOldscanObjCmd(
}
Tcl_ListObjAppendElement(interp, result, resultElement);
- TcNewObj(resultElement);
+ TclNewObj(resultElement);
if (yyHaveDay && !yyHaveDate) {
Tcl_ListObjAppendElement(interp, resultElement,
Tcl_NewIntObj((int) yyDayOrdinal));
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 6461909..bc1b1c6 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -4749,6 +4749,12 @@ Tcl_GetsObj(
ResetFlag(statePtr, CHANNEL_BLOCKED);
while (1) {
if (dst >= dstEnd) {
+ /*
+ * In case of encoding errors, state gets flag
+ * CHANNEL_ENCODING_ERROR set in the call below. First, the
+ * EOF/EOL condition is checked, as we may have valid data with
+ * EOF/EOL before the encoding error.
+ */
if (FilterInputBytes(chanPtr, &gs) != 0) {
goto restore;
}
@@ -4918,8 +4924,17 @@ Tcl_GetsObj(
}
goto gotEOL;
} else if (gs.bytesWrote == 0
- && GotFlag(statePtr, CHANNEL_ENCODING_ERROR)
- && !GotFlag(statePtr, CHANNEL_NONBLOCKING)) {
+ && GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
+ /* Ticket c4eb46a1 Harald Oehlmann 2023-11-12 debugging session.
+ * In non blocking mode we loop indifenitly on a decoding error in
+ * this while-loop.
+ * Removed the following from the upper condition:
+ * "&& !GotFlag(statePtr, CHANNEL_NONBLOCKING)"
+ * In case of an encoding error with leading correct bytes, we pass here
+ * two times, as gs.bytesWrote is not 0 on the first pass. This feels
+ * once to much, as the data is anyway not used.
+ */
+
/* Set eol to the position that caused the encoding error, and then
* continue to gotEOL, which stores the data that was decoded
* without error to objPtr. This allows the caller to do something
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 0b46184..3d8a702 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -2886,11 +2886,13 @@ typedef struct ProcessGlobalValue {
*/
#define ENCODING_PROFILE_MASK 0xFF000000
-#define ENCODING_PROFILE_GET(flags_) ((flags_) & ENCODING_PROFILE_MASK)
-#define ENCODING_PROFILE_SET(flags_, profile_) \
- do { \
- (flags_) &= ~ENCODING_PROFILE_MASK; \
- (flags_) |= profile_; \
+#define ENCODING_PROFILE_GET(flags_) (((flags_) & TCL_ENCODING_PROFILE_STRICT) ? \
+ TCL_ENCODING_PROFILE_STRICT : (((flags_) & ENCODING_PROFILE_MASK) ? \
+ ((flags_) & ENCODING_PROFILE_MASK) : TCL_ENCODING_PROFILE_TCL8))
+#define ENCODING_PROFILE_SET(flags_, profile_) \
+ do { \
+ (flags_) &= ~(ENCODING_PROFILE_MASK|TCL_ENCODING_PROFILE_STRICT); \
+ (flags_) |= (profile_) & (ENCODING_PROFILE_MASK|TCL_ENCODING_PROFILE_STRICT); \
} while (0)
/*
@@ -2916,7 +2918,6 @@ TclEncodingProfileNameToId(Tcl_Interp *interp,
int *profilePtr);
MODULE_SCOPE const char *TclEncodingProfileIdToName(Tcl_Interp *interp,
int profileId);
-MODULE_SCOPE int TclEncodingSetProfileFlags(int flags);
MODULE_SCOPE void TclGetEncodingProfiles(Tcl_Interp *interp);
/*
diff --git a/generic/tclInterp.c b/generic/tclInterp.c
index ed3c527..0325091 100644
--- a/generic/tclInterp.c
+++ b/generic/tclInterp.c
@@ -393,20 +393,25 @@ Tcl_Init(
" rename tclInit {}\n"
" if {[info exists tcl_library]} {\n"
" set scripts {{set tcl_library}}\n"
+"puts A-SCRIPTS:$scripts\n"
" } else {\n"
" set scripts {}\n"
" if {[info exists env(TCL_LIBRARY)] && ($env(TCL_LIBRARY) ne {})} {\n"
" lappend scripts {set env(TCL_LIBRARY)}\n"
+"puts B-SCRIPTS:$scripts\n"
" lappend scripts {\n"
"if {[regexp ^tcl(.*)$ [file tail $env(TCL_LIBRARY)] -> tail] == 0} continue\n"
"if {$tail eq [info tclversion]} continue\n"
"file join [file dirname $env(TCL_LIBRARY)] tcl[info tclversion]}\n"
+"puts C-SCRIPTS:$scripts\n"
" }\n"
-" lappend scripts {::tcl::zipfs::tcl_library_init}\n"
+"puts D-SCRIPTS:$scripts\n"
" if {[info exists tclDefaultLibrary]} {\n"
" lappend scripts {set tclDefaultLibrary}\n"
+"puts E-SCRIPTS:$scripts\n"
" } else {\n"
" lappend scripts {::tcl::pkgconfig get scriptdir,runtime}\n"
+"puts F-SCRIPTS:$scripts\n"
" }\n"
" lappend scripts {\n"
"set parentDir [file dirname [file dirname [info nameofexecutable]]]\n"
@@ -425,12 +430,14 @@ Tcl_Init(
" lappend scripts [list lindex \\$tcl_libPath $i]\n"
" }\n"
" }\n"
+"puts G-SCRIPTS:$scripts\n"
" }\n"
" set dirs {}\n"
" set errors {}\n"
" foreach script $scripts {\n"
" lappend dirs [eval $script]\n"
" set tcl_library [lindex $dirs end]\n"
+"puts TRIAL:$tcl_library\n"
" set tclfile [file join $tcl_library init.tcl]\n"
" if {[file exists $tclfile]} {\n"
" if {[catch {uplevel #0 [list source $tclfile]} msg opts]} {\n"
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c
index 24d9646..7a32fd9 100644
--- a/generic/tclNamesp.c
+++ b/generic/tclNamesp.c
@@ -2156,7 +2156,7 @@ DeleteImportedCmd(
* If "flags" contains TCL_CREATE_NS_IF_UNKNOWN, all namespace components
* of the qualified name that cannot be found are automatically created
* within their specified parent. This makes sure that functions like
- * Tcl_CreateCommand always succeed. There is no alternate search path,
+ * Tcl_CreateObjCommand always succeed. There is no alternate search path,
* so *altNsPtrPtr is set NULL.
*
* If "flags" contains TCL_FIND_ONLY_NS, the qualified name is treated as
@@ -2353,7 +2353,7 @@ TclGetNamespaceForQualName(
* Look up the namespace qualifier nsName in the current namespace
* context. If it isn't found but TCL_CREATE_NS_IF_UNKNOWN is set,
* create that qualifying namespace. This is needed for functions like
- * Tcl_CreateCommand that cannot fail.
+ * Tcl_CreateObjCommand that cannot fail.
*/
if (nsPtr != NULL) {
diff --git a/generic/tclTest.c b/generic/tclTest.c
index 895de64..efa045e 100644
--- a/generic/tclTest.c
+++ b/generic/tclTest.c
@@ -2086,7 +2086,7 @@ static int UtfExtWrapper(
} flagMap[] = {
{"start", TCL_ENCODING_START},
{"end", TCL_ENCODING_END},
- {"stoponerror", TCL_ENCODING_STOPONERROR},
+ {"stoponerror", TCL_ENCODING_PROFILE_STRICT},
{"noterminate", TCL_ENCODING_NO_TERMINATE},
{"charlimit", TCL_ENCODING_CHAR_LIMIT},
{"profiletcl8", TCL_ENCODING_PROFILE_TCL8},
diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c
index 842d51a..5400f92 100644
--- a/generic/tclZipfs.c
+++ b/generic/tclZipfs.c
@@ -91,6 +91,17 @@ static const z_crc_t* crc32tab;
#define ZIPFS_VOLUME_LEN 9
#define ZIPFS_APP_MOUNT ZIPFS_VOLUME "app"
#define ZIPFS_ZIP_MOUNT ZIPFS_VOLUME "lib/tcl"
+
+#define ZIPFS_SCRIPT_PREFIX "set ::tcl_library "
+#define ZIPFS_TCL_LIBRARY_1 ZIPFS_APP_MOUNT "/tcl_library"
+#define ZIPFS_INIT_SCRIPT_1 ZIPFS_SCRIPT_PREFIX ZIPFS_TCL_LIBRARY_1
+
+#define ZIPFS_TCL_LIBRARY_2 ZIPFS_ZIP_MOUNT
+#define ZIPFS_INIT_SCRIPT_2 ZIPFS_SCRIPT_PREFIX ZIPFS_TCL_LIBRARY_2
+
+#define ZIPFS_TCL_LIBRARY_3 ZIPFS_ZIP_MOUNT "/tcl_library"
+#define ZIPFS_INIT_SCRIPT_3 ZIPFS_SCRIPT_PREFIX ZIPFS_TCL_LIBRARY_3
+
#define ZIPFS_FALLBACK_ENCODING "cp437"
/*
@@ -313,6 +324,7 @@ static const char pwrot[17] =
"\x10\x90\x50\xD0\x30\xB0\x70\xF0";
static const char *zipfs_literal_tcl_library = NULL;
+static const char *zipfs_init_script = NULL;
/* Function prototypes */
@@ -906,7 +918,7 @@ DecodeZipEntryText(
dst = Tcl_DStringValue(dstPtr);
dstLen = dstPtr->spaceAvl - 1;
flags = TCL_ENCODING_START | TCL_ENCODING_END |
- TCL_ENCODING_STOPONERROR; /* Special flag! */
+ TCL_ENCODING_PROFILE_STRICT; /* Special flag! */
while (1) {
int srcRead, dstWrote;
@@ -4231,6 +4243,28 @@ ScriptLibrarySetup(
Tcl_Obj *libDirObj = Tcl_NewStringObj(dirName, -1);
Tcl_Obj *subDirObj, *searchPathObj;
+ /*
+ * We know where the init.tcl is located in the attached script library
+ * archive. Use a pre-init script to tell every Tcl interp as it gets
+ * created where that is, so none of them need to construct and then
+ * iterate through some search path. That's the literal documented
+ * purpose of Tcl_SetPreInitScript(). Use it.
+ *
+ * TODO: Examine why we need so many variations and eliminate as many
+ * as possible.
+ */
+
+ if (0 == strcmp(zipfs_literal_tcl_library, ZIPFS_TCL_LIBRARY_1)) {
+ zipfs_init_script = ZIPFS_INIT_SCRIPT_1;
+ } else if (0 == strcmp(zipfs_literal_tcl_library, ZIPFS_TCL_LIBRARY_2)) {
+ zipfs_init_script = ZIPFS_INIT_SCRIPT_2;
+ } else if (0 == strcmp(zipfs_literal_tcl_library, ZIPFS_TCL_LIBRARY_3)) {
+ zipfs_init_script = ZIPFS_INIT_SCRIPT_3;
+ }
+ if (zipfs_init_script) {
+ Tcl_SetPreInitScript(zipfs_init_script);
+ }
+
TclNewLiteralStringObj(subDirObj, "encoding");
Tcl_IncrRefCount(subDirObj);
TclNewObj(searchPathObj);
@@ -4238,6 +4272,7 @@ ScriptLibrarySetup(
Tcl_FSJoinToPath(libDirObj, 1, &subDirObj));
Tcl_DecrRefCount(subDirObj);
Tcl_IncrRefCount(searchPathObj);
+fprintf(stdout, "AH CALLER\n"); fflush(stdout);
Tcl_SetEncodingSearchPath(searchPathObj);
Tcl_DecrRefCount(searchPathObj);
return libDirObj;
@@ -4268,13 +4303,12 @@ TclZipfs_TclLibrary(void)
* Look for the library file system within the executable.
*/
- vfsInitScript = Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl",
- -1);
+ vfsInitScript = Tcl_NewStringObj(ZIPFS_TCL_LIBRARY_1 "/init.tcl", -1);
Tcl_IncrRefCount(vfsInitScript);
found = Tcl_FSAccess(vfsInitScript, F_OK);
Tcl_DecrRefCount(vfsInitScript);
if (found == TCL_OK) {
- zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library";
+ zipfs_literal_tcl_library = ZIPFS_TCL_LIBRARY_1;
return ScriptLibrarySetup(zipfs_literal_tcl_library);
}
@@ -4323,44 +4357,6 @@ TclZipfs_TclLibrary(void)
/*
*-------------------------------------------------------------------------
*
- * ZipFSTclLibraryObjCmd --
- *
- * This procedure is invoked to process the
- * [::tcl::zipfs::tcl_library_init] command, usually called during the
- * execution of Tcl's interpreter startup. It returns the root that Tcl's
- * library files are mounted under.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * May initialise the cache of where such library files are to be found.
- * This cache is never cleared.
- *
- *-------------------------------------------------------------------------
- */
-
-static int
-ZipFSTclLibraryObjCmd(
- TCL_UNUSED(void *),
- Tcl_Interp *interp, /* Current interpreter. */
- TCL_UNUSED(int) /*objc*/,
- TCL_UNUSED(Tcl_Obj *const *)) /*objv*/
-{
- if (!Tcl_IsSafe(interp)) {
- Tcl_Obj *pResult = TclZipfs_TclLibrary();
-
- if (!pResult) {
- TclNewObj(pResult);
- }
- Tcl_SetObjResult(interp, pResult);
- }
- return TCL_OK;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
* ZipChannelClose --
*
* This function is called to close a channel.
@@ -6253,8 +6249,6 @@ TclZipfs_Init(
Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj);
Tcl_DictObjPut(NULL, mapObj, Tcl_NewStringObj("find", -1),
Tcl_NewStringObj("::tcl::zipfs::find", -1));
- Tcl_CreateObjCommand(interp, "::tcl::zipfs::tcl_library_init",
- ZipFSTclLibraryObjCmd, NULL, NULL);
Tcl_PkgProvide(interp, "tcl::zipfs", "2.0");
}
return TCL_OK;
@@ -6283,22 +6277,21 @@ ZipfsAppHookFindTclInit(
return TCL_ERROR;
}
- TclNewLiteralStringObj(vfsInitScript, ZIPFS_ZIP_MOUNT "/init.tcl");
+ TclNewLiteralStringObj(vfsInitScript, ZIPFS_TCL_LIBRARY_2 "/init.tcl");
Tcl_IncrRefCount(vfsInitScript);
found = Tcl_FSAccess(vfsInitScript, F_OK);
Tcl_DecrRefCount(vfsInitScript);
if (found == 0) {
- zipfs_literal_tcl_library = ZIPFS_ZIP_MOUNT;
+ zipfs_literal_tcl_library = ZIPFS_TCL_LIBRARY_2;
return TCL_OK;
}
- TclNewLiteralStringObj(vfsInitScript,
- ZIPFS_ZIP_MOUNT "/tcl_library/init.tcl");
+ TclNewLiteralStringObj(vfsInitScript, ZIPFS_TCL_LIBRARY_3 "/init.tcl");
Tcl_IncrRefCount(vfsInitScript);
found = Tcl_FSAccess(vfsInitScript, F_OK);
Tcl_DecrRefCount(vfsInitScript);
if (found == 0) {
- zipfs_literal_tcl_library = ZIPFS_ZIP_MOUNT "/tcl_library";
+ zipfs_literal_tcl_library = ZIPFS_TCL_LIBRARY_3;
return TCL_OK;
}
@@ -6415,12 +6408,13 @@ TclZipfs_AppHook(
if (!zipfs_literal_tcl_library) {
TclNewLiteralStringObj(vfsInitScript,
- ZIPFS_APP_MOUNT "/tcl_library/init.tcl");
+ ZIPFS_TCL_LIBRARY_1 "/init.tcl");
Tcl_IncrRefCount(vfsInitScript);
found = Tcl_FSAccess(vfsInitScript, F_OK);
Tcl_DecrRefCount(vfsInitScript);
if (found == TCL_OK) {
- zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library";
+ zipfs_literal_tcl_library = ZIPFS_TCL_LIBRARY_1;
+ Tcl_DecrRefCount(TclZipfs_TclLibrary());
return version;
}
}
@@ -6447,9 +6441,9 @@ TclZipfs_AppHook(
* wants it.
*/
- TclZipfs_TclLibrary();
+ Tcl_DecrRefCount(TclZipfs_TclLibrary());
TclNewLiteralStringObj(vfsInitScript,
- ZIPFS_ZIP_MOUNT "/tcl_library/install.tcl");
+ ZIPFS_TCL_LIBRARY_3 "install.tcl");
Tcl_IncrRefCount(vfsInitScript);
if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
Tcl_SetStartupScript(vfsInitScript, NULL);
@@ -6459,6 +6453,17 @@ TclZipfs_AppHook(
int found;
Tcl_Obj *vfsInitScript;
+ /* Set Tcl Encodings */
+ TclNewLiteralStringObj(vfsInitScript,
+ ZIPFS_TCL_LIBRARY_1 "/init.tcl");
+ Tcl_IncrRefCount(vfsInitScript);
+ found = Tcl_FSAccess(vfsInitScript, F_OK);
+ Tcl_DecrRefCount(vfsInitScript);
+ if (found == TCL_OK) {
+ zipfs_literal_tcl_library = ZIPFS_TCL_LIBRARY_1;
+ Tcl_DecrRefCount(TclZipfs_TclLibrary());
+ }
+
TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
Tcl_IncrRefCount(vfsInitScript);
if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
@@ -6470,14 +6475,8 @@ TclZipfs_AppHook(
} else {
Tcl_DecrRefCount(vfsInitScript);
}
- /* Set Tcl Encodings */
- TclNewLiteralStringObj(vfsInitScript,
- ZIPFS_APP_MOUNT "/tcl_library/init.tcl");
- Tcl_IncrRefCount(vfsInitScript);
- found = Tcl_FSAccess(vfsInitScript, F_OK);
- Tcl_DecrRefCount(vfsInitScript);
+
if (found == TCL_OK) {
- zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library";
return version;
}
}
diff --git a/tests/io.test b/tests/io.test
index 9f731ad..7e62e6b 100644
--- a/tests/io.test
+++ b/tests/io.test
@@ -9193,7 +9193,7 @@ test io-75.5 {invalid utf-8 encoding read is ignored (-profile tcl8)} -setup {
removeFile io-75.5
} -result 4181
-test io-75.6 {invalid utf-8 encoding, gets is not ignored (-profile strict)} -setup {
+test io-75.6 {incomplete utf-8 encoding, blocking gets is not ignored (-profile strict)} -setup {
set fn [makeFile {} io-75.6]
set f [open $fn w+]
fconfigure $f -encoding binary
@@ -9211,6 +9211,84 @@ test io-75.6 {invalid utf-8 encoding, gets is not ignored (-profile strict)} -se
} -match glob -returnCodes 1 -result {error reading "file*":\
invalid or incomplete multibyte or wide character}
+test io-75.6.1 {invalid utf-8 encoding, blocking gets is not ignored (-profile strict)} -setup {
+ set fn [makeFile {} io-75.6.1]
+ set f [open $fn w+]
+ fconfigure $f -encoding binary
+ # utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
+ puts -nonewline $f A\xC3B
+ flush $f
+ seek $f 0
+ fconfigure $f -encoding utf-8 -buffering none -eofchar {} \
+ -translation lf -profile strict
+} -body {
+ gets $f
+} -cleanup {
+ close $f
+ removeFile io-75.6.1
+} -match glob -returnCodes 1 -result {error reading "file*":\
+ invalid or incomplete multibyte or wide character}
+
+test io-75.6.2 {invalid utf-8 encoding, blocking gets is not ignored (-profile strict), recover functionality} -setup {
+ set fn [makeFile {} io-75.6.2]
+ set f [open $fn w+]
+ fconfigure $f -encoding binary
+ # utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
+ puts -nonewline $f A\xC3B
+ flush $f
+ seek $f 0
+ fconfigure $f -encoding utf-8 -buffering none -eofchar {} \
+ -translation lf -profile strict
+} -body {
+ set l {}
+ lappend l [catch {gets $f}]
+ lappend l [tell $f]
+ fconfigure $f -encoding binary
+ lappend l [expr {[gets $f] eq "A\xC3B"}]
+} -cleanup {
+ close $f
+ removeFile io-75.6.2
+} -match glob -returnCodes 0 -result {1 0 1}
+
+# TCL ticket c4eb46a196: non blocking case had endless loop, so test it
+test io-75.6.3 {invalid utf-8 encoding, non blocking gets is not ignored (-profile strict)} -setup {
+ set fn [makeFile {} io-75.6.3]
+ set f [open $fn w+]
+ fconfigure $f -encoding binary
+ # utf-8: \xC3 requires a 2nd byte > x80, but <x80 is delivered
+ puts -nonewline $f A\xC3B
+ flush $f
+ seek $f 0
+ fconfigure $f -encoding utf-8 -buffering none -eofchar {} \
+ -translation lf -profile strict -blocking 0
+} -body {
+ gets $f
+} -cleanup {
+ close $f
+ removeFile io-75.6.3
+} -match glob -returnCodes 1 -result {error reading "file*":\
+ invalid or incomplete multibyte or wide character}
+
+test io-75.6.4 {incomplete utf-8 encoding, non blocking gets is not ignored (-profile strict)} -setup {
+ set fn [makeFile {} io-75.6.4]
+ set f [open $fn w+]
+ fconfigure $f -encoding binary
+ # \x81 is an incomplete byte sequence in utf-8
+ puts -nonewline $f A\x81
+ flush $f
+ seek $f 0
+ fconfigure $f -encoding utf-8 -buffering none -eofchar {} \
+ -translation lf -profile strict -blocking 0
+} -body {
+ gets $f
+ # only the 2nd gets returns the error
+ gets $f
+} -cleanup {
+ close $f
+ removeFile io-75.6.4
+} -match glob -returnCodes 1 -result {error reading "file*":\
+ invalid or incomplete multibyte or wide character}
+
test io-75.7 {
invalid utf-8 encoding read is not ignored (-profile strict)
} -setup {
@@ -9232,7 +9310,7 @@ test io-75.7 {
} -match glob -result {1 {error reading "file*":\
invalid or incomplete multibyte or wide character}}
-test io-75.8 {invalid utf-8 encoding eof handling (-profile strict)} -setup {
+test io-75.8 {invalid utf-8 encoding eof first handling (-profile strict)} -setup {
set fn [makeFile {} io-75.8]
set f [open $fn w+]
fconfigure $f -encoding binary
@@ -9254,7 +9332,7 @@ test io-75.8 {invalid utf-8 encoding eof handling (-profile strict)} -setup {
removeFile io-75.8
} -result {41 1 {}}
-test io-75.8.eoflater {invalid utf-8 encoding eof handling (-profile strict)} -setup {
+test io-75.8.eoflater {invalid utf-8 encoding eof after handling (-profile strict)} -setup {
set fn [makeFile {} io-75.8]
set f [open $fn w+]
# This also configures the channel encoding profile as strict.
diff --git a/unix/Makefile.in b/unix/Makefile.in
index 29a28eb..a081bb8 100644
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -2106,6 +2106,8 @@ dist-packages: configure-packages
# the name of the .y file so that make doesn't try to automatically regenerate
# the .c file.
+#
+# Remark: see [54a305cb88]. tclDate.c is manually edited, removing the unused "yynerrs" variable
gendate:
bison --output-file=$(GENERIC_DIR)/tclDate.c \
--no-lines \
diff --git a/unix/tclAppInit.c b/unix/tclAppInit.c
index b203487..04ae564 100644
--- a/unix/tclAppInit.c
+++ b/unix/tclAppInit.c
@@ -148,7 +148,7 @@ Tcl_AppInit(
*/
/*
- * Call Tcl_CreateCommand for application-specific commands, if they
+ * Call Tcl_CreateObjCommand for application-specific commands, if they
* weren't already created by the init procedures called above.
*/
diff --git a/win/tclAppInit.c b/win/tclAppInit.c
index a3914f1..d1b38ee 100644
--- a/win/tclAppInit.c
+++ b/win/tclAppInit.c
@@ -204,7 +204,7 @@ Tcl_AppInit(
*/
/*
- * Call Tcl_CreateCommand for application-specific commands, if they
+ * Call Tcl_CreateObjCommand for application-specific commands, if they
* weren't already created by the init procedures called above.
*/