From 6fdeeafb88751dde97a0c3103cc6b71d76e2fcd0 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Mon, 15 Oct 2007 02:02:47 +0000 Subject: [PATCH] [Tcl] Prevent SWIG_Tcl_ConvertPtr from calling the unknown proc. Add Examples/tcl/std_vector/ which this change fixes. Patch is from "Cliff C" in SF#1809819. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9989 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- CHANGES.current | 5 ++++ Examples/tcl/check.list | 1 + Examples/tcl/std_vector/Makefile | 20 ++++++++++++++++ Examples/tcl/std_vector/example.h | 25 +++++++++++++++++++ Examples/tcl/std_vector/example.i | 17 +++++++++++++ Examples/tcl/std_vector/runme.tcl | 40 +++++++++++++++++++++++++++++++ Lib/tcl/tclrun.swg | 33 +++++++++++++++++++++---- 7 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 Examples/tcl/std_vector/Makefile create mode 100644 Examples/tcl/std_vector/example.h create mode 100644 Examples/tcl/std_vector/example.i create mode 100644 Examples/tcl/std_vector/runme.tcl diff --git a/CHANGES.current b/CHANGES.current index a411d38fb..0d6210a24 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,6 +1,11 @@ Version 1.3.32 (in progress) ============================ +10/15/2007: olly + [Tcl] Prevent SWIG_Tcl_ConvertPtr from calling the unknown proc. + Add Examples/tcl/std_vector/ which this change fixes. Patch + is from "Cliff C" in SF#1809819. + 10/12/2007: wuzzeb Added a testsuite entry for Bug #1735931 diff --git a/Examples/tcl/check.list b/Examples/tcl/check.list index 9f7e1b11e..8e7a8a9d7 100644 --- a/Examples/tcl/check.list +++ b/Examples/tcl/check.list @@ -11,5 +11,6 @@ operator pointer reference simple +std_vector value variables diff --git a/Examples/tcl/std_vector/Makefile b/Examples/tcl/std_vector/Makefile new file mode 100644 index 000000000..ce6a3c7ce --- /dev/null +++ b/Examples/tcl/std_vector/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/std_vector/example.h b/Examples/tcl/std_vector/example.h new file mode 100644 index 000000000..4f0dac70d --- /dev/null +++ b/Examples/tcl/std_vector/example.h @@ -0,0 +1,25 @@ +/* File : example.h */ + +#include +#include +#include +#include + +double average(std::vector v) { + return std::accumulate(v.begin(),v.end(),0.0)/v.size(); +} + +std::vector half(const std::vector& v) { + std::vector w(v); + for (unsigned int i=0; i& v) { + // would you believe this is the same as the above? + std::transform(v.begin(),v.end(),v.begin(), + std::bind2nd(std::divides(),2.0)); +} + + diff --git a/Examples/tcl/std_vector/example.i b/Examples/tcl/std_vector/example.i new file mode 100644 index 000000000..aa58b66e0 --- /dev/null +++ b/Examples/tcl/std_vector/example.i @@ -0,0 +1,17 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +%include stl.i +/* instantiate the required template specializations */ +namespace std { + %template(IntVector) vector; + %template(DoubleVector) vector; +} + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/tcl/std_vector/runme.tcl b/Examples/tcl/std_vector/runme.tcl new file mode 100644 index 000000000..2cece9691 --- /dev/null +++ b/Examples/tcl/std_vector/runme.tcl @@ -0,0 +1,40 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +# Exercise IntVector + +set iv [IntVector] +$iv push 1 +$iv push 3 +$iv push 5 + +puts "IntVector size: [$iv size] (should be 3)" +puts "IntVector average: [average $iv] (should be 3.0)" +puts "IntVector pop: [$iv pop] (should be 5)" +puts "IntVector pop: [$iv pop] (should be 3)" +puts "IntVector get 0: [$iv get 0] (should be 1)" +puts "" + +# Exercise DoubleVector + +set dv [DoubleVector] +$dv push 2 +$dv push 4 +$dv push 6 + +puts "DoubleVector size: [$dv size] (should be 3)" +puts "DoubleVector data: [$dv get 0] [$dv get 1] [$dv get 2] (should be 2.0 4.0 6.0)" +halve_in_place $dv +puts "DoubleVector halved: [$dv get 0] [$dv get 1] [$dv get 2] (should be 1.0 2.0 3.0)" +puts "" + +# Complain if unknown is called +rename unknown unknown_orig +proc unknown {args} { + puts "ERROR: unknown called with: $args" + uplevel 1 unknown_orig $args +} + +puts "average \"1 2 3\": [average [list 1 2 3]]" + diff --git a/Lib/tcl/tclrun.swg b/Lib/tcl/tclrun.swg index 538b8f310..d4a680bda 100644 --- a/Lib/tcl/tclrun.swg +++ b/Lib/tcl/tclrun.swg @@ -125,15 +125,38 @@ SWIG_Tcl_ConvertPtrFromString(Tcl_Interp *interp, const char *c, void **ptr, swi while (*c != '_') { *ptr = (void *) 0; if (strcmp(c,"NULL") == 0) return SWIG_OK; + + /* Empty string: not a pointer */ + if (*c == 0) return SWIG_ERROR; + /* Hmmm. It could be an object name. */ - if (Tcl_VarEval(interp,c," cget -this", (char *) NULL) == TCL_OK) { + + /* Check if this is a command at all. Prevents cget -this */ + /* from being called when c is not a command, firing the unknown proc */ + if (Tcl_VarEval(interp,"info commands ", c, (char *) NULL) == TCL_OK) { Tcl_Obj *result = Tcl_GetObjResult(interp); - c = Tcl_GetStringFromObj(result, NULL); - continue; + if (*(Tcl_GetStringFromObj(result, NULL)) == 0) { + /* It's not a command, so it can't be a pointer */ + Tcl_ResetResult(interp); + return SWIG_ERROR; + } + } else { + /* This will only fail if the argument is multiple words. */ + /* Multiple words are also not commands. */ + Tcl_ResetResult(interp); + return SWIG_ERROR; } - Tcl_ResetResult(interp); - return SWIG_ERROR; + + /* Check if this is really a SWIG pointer */ + if (Tcl_VarEval(interp,c," cget -this", (char *) NULL) != TCL_OK) { + Tcl_ResetResult(interp); + return SWIG_ERROR; + } + + Tcl_Obj *result = Tcl_GetObjResult(interp); + c = Tcl_GetStringFromObj(result, NULL); } + c++; c = SWIG_UnpackData(c,ptr,sizeof(void *)); if (ty) {