summaryrefslogtreecommitdiffstats
path: root/generic/tclStubLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclStubLib.c')
-rw-r--r--generic/tclStubLib.c52
1 files changed, 43 insertions, 9 deletions
diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c
index 0efaf50..96f7f2f 100644
--- a/generic/tclStubLib.c
+++ b/generic/tclStubLib.c
@@ -34,11 +34,12 @@ const TclIntPlatStubs *tclIntPlatStubsPtr = NULL;
static const TclStubs *
HasStubSupport(
- Tcl_Interp *interp)
+ Tcl_Interp *interp,
+ int magic)
{
Interp *iPtr = (Interp *) interp;
-
- if (iPtr->stubTable && (iPtr->stubTable->magic == TCL_STUB_MAGIC)) {
+ if (iPtr->stubTable && iPtr->stubTable->magic == magic
+ && iPtr->stubTable->magic == TCL_STUB_MAGIC) {
return iPtr->stubTable;
}
iPtr->result = (char *) "interpreter uses an incompatible stubs mechanism";
@@ -58,7 +59,7 @@ static int isDigit(const int c)
/*
*----------------------------------------------------------------------
*
- * Tcl_InitStubs --
+ * TclInitStubs --
*
* Tries to initialise the stub table pointers and ensures that the
* correct version of Tcl is loaded.
@@ -74,13 +75,19 @@ static int isDigit(const int c)
*/
MODULE_SCOPE const char *
-Tcl_InitStubs(
+TclInitStubs(
Tcl_Interp *interp,
const char *version,
- int exact)
+ int exact,
+ const char *tclversion,
+ int magic)
{
+ const char *p;
+ char *q;
+ char major[TCL_INTEGER_SPACE];
const char *actualVersion = NULL;
ClientData pkgData = NULL;
+ Interp *iPtr = (Interp *) interp;
/*
* We can't optimize this check by caching tclStubsPtr because that
@@ -88,24 +95,51 @@ Tcl_InitStubs(
* times. [Bug 615304]
*/
- tclStubsPtr = HasStubSupport(interp);
+ tclStubsPtr = HasStubSupport(interp, magic);
if (!tclStubsPtr) {
return NULL;
}
+ /*
+ * Check that the [load]ing interp and [load]ed extension were compiled
+ * against headers from the same major version of Tcl. If not, they
+ * will not agree on the layout of the stubs and will crash. Report
+ * the error instead of crashing.
+ */
+
+ p = tclversion;
+ q = major;
+ while (isDigit(*p)) {
+ *q++ = *p++;
+ if (q-major > TCL_INTEGER_SPACE) {
+ iPtr->result = (char *) "major version overflow";
+ iPtr->freeProc = TCL_STATIC;
+ return NULL;
+ }
+ }
+ *q = '\0';
+
+ if (NULL == Tcl_PkgRequireEx(interp, "Tcl", major, 0, NULL)) {
+ return NULL;
+ }
+
+ /*
+ * Check satisfaction of the requirement requested by the caller.
+ */
+
actualVersion = Tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData);
if (actualVersion == NULL) {
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)) {