diff options
Diffstat (limited to 'generic/tclStubLib.c')
-rw-r--r-- | generic/tclStubLib.c | 52 |
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)) { |