summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tcl.h9
-rw-r--r--generic/tclStubLib.c51
2 files changed, 53 insertions, 7 deletions
diff --git a/generic/tcl.h b/generic/tcl.h
index fa6afe4..c7b9e6a 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -2281,8 +2281,8 @@ typedef int (Tcl_NRPostProc) (ClientData data[], Tcl_Interp *interp,
* main library in case an extension is statically linked into an application.
*/
-const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version,
- int exact);
+const char * TclInitStubs(Tcl_Interp *interp, const char *version,
+ int exact, int major, int magic);
const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
const char *version, int epoch, int revision);
@@ -2290,7 +2290,10 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
* When not using stubs, make it a macro.
*/
-#ifndef USE_TCL_STUBS
+#ifdef USE_TCL_STUBS
+#define Tcl_InitStubs(interp, version, exact) \
+ TclInitStubs(interp, version, exact, TCL_MAJOR_VERSION, TCL_STUB_MAGIC)
+#else
#define Tcl_InitStubs(interp, version, exact) \
Tcl_PkgInitStubsCheck(interp, version, exact)
#endif
diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c
index fe1302c..e875bf7 100644
--- a/generic/tclStubLib.c
+++ b/generic/tclStubLib.c
@@ -101,13 +101,56 @@ static int isDigit(const int c)
*/
MODULE_SCOPE const char *
-Tcl_InitStubs(
+TclInitStubs(
Tcl_Interp *interp,
const char *version,
- int exact)
+ int exact,
+ int major,
+ int magic)
{
+ Interp *iPtr = (Interp *) interp;
const char *actualVersion = NULL;
ClientData pkgData = NULL;
+ const char *p, *q;
+
+ /*
+ * Detect whether the extension and the stubs library were built
+ * against Tcl header files declaring use of incompatible stubs
+ * mechanisms. Even within the same mechanism, also detect if
+ * the header files are from different major versions. Either
+ * is seriously broken. An extension and its stubs library ought
+ * to share compatible headers, if not the same one.
+ */
+
+ if (magic != TCL_STUB_MAGIC || major != TCL_MAJOR_VERSION) {
+ iPtr->legacyResult =
+ (char *) "extension linked to incompatible stubs library";
+ iPtr->legacyFreeProc = TCL_STATIC;
+ return NULL;
+ }
+
+ /*
+ * Detect whether an extension compiled against a Tcl header file
+ * of one major version is requesting to use a stubs table of a
+ * different major version. According to our compat rules, that's
+ * a request that cannot succeed. Different major versions imply
+ * incompatible stub tables.
+ */
+
+ p = version;
+ q = TCL_VERSION;
+ while (isDigit(*p)) {
+ if (*p++ != *q++) {
+ goto badVersion;
+ }
+ }
+ if (isDigit(*q)) {
+ badVersion:
+ iPtr->legacyResult =
+ (char *) "extension passed bad version argument to stubs library";
+ iPtr->legacyFreeProc = TCL_STATIC;
+ return NULL;
+ }
/*
* We can't optimize this check by caching tclStubsPtr because that
@@ -125,14 +168,14 @@ Tcl_InitStubs(
return NULL;
}
if (exact) {
- const char *p = version;
int count = 0;
+ p = version;
while (*p) {
count += !isDigit(*p++);
}
if (count == 1) {
- const char *q = actualVersion;
+ q = actualVersion;
p = version;
while (*p && (*p == *q)) {