diff options
Diffstat (limited to 'generic/tclStubLib.c')
-rw-r--r-- | generic/tclStubLib.c | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index bd80ec1..f1229d5 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -34,29 +34,17 @@ const TclIntPlatStubs *tclIntPlatStubsPtr = NULL; static const TclStubs * HasStubSupport( - Tcl_Interp *interp, - int magic) + Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; - if (!iPtr->stubTable) { - /* No stub table at all? Nothing we can do. */ - return NULL; - } - if (iPtr->stubTable->magic != magic) { - /* - * The iPtr->stubTable entry from Tcl_Interp and the - * Tcl_NewStringObj() and Tcl_SetObjResult() entries - * in the stub table cannot change in Tcl 9 compared - * to Tcl 8.x. Otherwise the lines below won't work. - * TODO: add a test case for that. - */ - iPtr->stubTable->tcl_SetObjResult(interp, - iPtr->stubTable->tcl_NewStringObj( - "This extension is compiled for Tcl 9.x", -1)); - return NULL; + if (iPtr->stubTable && iPtr->stubTable->magic == TCL_STUB_MAGIC) { + return iPtr->stubTable; } - return iPtr->stubTable; + iPtr->result = + (char *) "interpreter uses an incompatible stubs mechanism"; + iPtr->freeProc = TCL_STATIC; + return NULL; } /* @@ -91,10 +79,52 @@ TclInitStubs( Tcl_Interp *interp, const char *version, 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->result = + (char *) "extension linked to incompatible stubs library"; + iPtr->freeProc = 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->result = (char *) + "extension passed bad version argument to stubs library"; + iPtr->freeProc = TCL_STATIC; + return NULL; + } /* * We can't optimize this check by caching tclStubsPtr because that @@ -102,7 +132,7 @@ TclInitStubs( * times. [Bug 615304] */ - tclStubsPtr = HasStubSupport(interp, magic); + tclStubsPtr = HasStubSupport(interp); if (!tclStubsPtr) { return NULL; } @@ -112,14 +142,14 @@ TclInitStubs( return NULL; } if (exact) { - const char *p = version; + p = version; int count = 0; while (*p) { count += !isDigit(*p++); } if (count == 1) { - const char *q = actualVersion; + q = actualVersion; p = version; while (*p && (*p == *q)) { |