summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2012-11-27 21:09:20 (GMT)
committerdgp <dgp@users.sourceforge.net>2012-11-27 21:09:20 (GMT)
commit3c5544ba3c952c9e4415f040bfe93cb22041d02c (patch)
treea40ae2bb7553c52bfc8565fa7fdc31bb72ddca2c
parent3c5b4af0d42e9175d48a6e114ec5f3ec05e1b915 (diff)
downloadtcl-3c5544ba3c952c9e4415f040bfe93cb22041d02c.zip
tcl-3c5544ba3c952c9e4415f040bfe93cb22041d02c.tar.gz
tcl-3c5544ba3c952c9e4415f040bfe93cb22041d02c.tar.bz2
3588687 Added cross checks so that [load]ed extension, [load]ing interp, and
linked stubs library all agree on their versions in the ways that matter.
-rw-r--r--generic/tcl.h9
-rw-r--r--generic/tclStubLib.c57
2 files changed, 59 insertions, 7 deletions
diff --git a/generic/tcl.h b/generic/tcl.h
index 147672c..74dd452 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -2394,8 +2394,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);
const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
const char *version, int epoch, int revision);
@@ -2403,7 +2403,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)
+#else
#define Tcl_InitStubs(interp, version, exact) \
Tcl_PkgInitStubsCheck(interp, version, exact)
#endif
diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c
index f569820..ca6f4ff 100644
--- a/generic/tclStubLib.c
+++ b/generic/tclStubLib.c
@@ -76,13 +76,52 @@ 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)
{
+ 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 from different major versions. That's
+ * seriously broken.
+ */
+
+ if (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
@@ -100,14 +139,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)) {
@@ -140,6 +179,16 @@ Tcl_InitStubs(
return actualVersion;
}
+#undef Tcl_InitStubs
+MODULE_SCOPE const char *
+Tcl_InitStubs(
+ Tcl_Interp *interp,
+ const char *version,
+ int exact)
+{
+ return TclInitStubs(interp, version, exact, TCL_MAJOR_VERSION);
+}
+
/*
* Local Variables:
* mode: c