Fix directorin SWIGTYPE typemaps to make a copy as these are used for pass by value.

Closes #434
This commit is contained in:
William S Fulton 2016-05-14 21:19:14 +01:00
commit 98a31ff633
15 changed files with 180 additions and 14 deletions

View file

@ -5,6 +5,13 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 3.0.9 (in progress)
===========================
2016-05-14: wsfulton
Fix #434 - Passing classes by value as parameters in director methods did not create
a copy of the argument leading to invalid memory accesses if the object was used
after the upcall into the target language. Passing arguments by value shouldn't give
rise to these sorts of memory problems and so the objects are now copied and ownership
of their lifetime is controlled by the target language.
2016-05-07: wsfulton
Fix #611. Fix assertion handling defaultargs when using %extend for a template
class and the extended methods contain default arguments.

View file

@ -174,7 +174,6 @@ CPP_TEST_CASES += \
director_abstract \
director_alternating \
director_basic \
director_property \
director_binary_string \
director_classes \
director_classic \
@ -189,12 +188,14 @@ CPP_TEST_CASES += \
director_ignore \
director_keywords \
director_namespace_clash \
director_nested \
director_nspace \
director_nspace_director_name_collision \
director_nested \
director_overload \
director_overload2 \
director_pass_by_value \
director_primitives \
director_property \
director_protected \
director_protected_overloaded \
director_redefined \

View file

@ -0,0 +1,43 @@
using System;
using director_pass_by_valueNamespace;
public class runme
{
private static void WaitForGC()
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.Threading.Thread.Sleep(10);
}
static void Main()
{
runme r = new runme();
r.run();
}
void run()
{
Caller caller = new Caller();
caller.call_virtualMethod(new director_pass_by_value_Derived());
{
int countdown = 5;
while (true) {
WaitForGC();
if (--countdown == 0)
break;
};
}
// bug was the passByVal 'global' object was destroyed after the call to virtualMethod had finished.
int ret = runme.passByVal.getVal();
if (ret != 0x12345678)
throw new Exception("Bad return value, got " + ret.ToString("x"));
}
public static PassedByValue passByVal;
}
class director_pass_by_value_Derived : DirectorPassByValueAbstractBase {
public override void virtualMethod(PassedByValue pbv) {
runme.passByVal = pbv;
}
}

View file

@ -0,0 +1,30 @@
%module(directors="1") director_pass_by_value
%director DirectorPassByValueAbstractBase;
%inline %{
class PassedByValue {
int val;
public:
PassedByValue() { val = 0x12345678; }
int getVal() { return val; }
};
int doSomething(int x) {
int yy[256];
yy[0] =0x9876;
return yy[0];
}
class DirectorPassByValueAbstractBase {
public:
virtual void virtualMethod(PassedByValue pbv) = 0;
virtual ~DirectorPassByValueAbstractBase () {}
};
class Caller {
public:
void call_virtualMethod(DirectorPassByValueAbstractBase &f) {
f.virtualMethod(PassedByValue());
}
};
%}

View file

@ -0,0 +1,48 @@
import director_pass_by_value.*;
public class director_pass_by_value_runme {
static {
try {
System.loadLibrary("director_pass_by_value");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
private static void WaitForGC() {
System.gc();
System.runFinalization();
try {
java.lang.Thread.sleep(10);
} catch (java.lang.InterruptedException e) {
}
}
public static void main(String argv[]) {
Caller caller = new Caller();
caller.call_virtualMethod(new director_pass_by_value_Derived());
{
int countdown = 5;
while (true) {
WaitForGC();
if (--countdown == 0)
break;
};
}
// bug was the passByVal 'global' object was destroyed after the call to virtualMethod had finished.
int ret = director_pass_by_value_runme.passByVal.getVal();
if (ret != 0x12345678)
throw new RuntimeException("Bad return value, got " + Integer.toHexString(ret));
}
static PassedByValue passByVal;
}
class director_pass_by_value_Derived extends DirectorPassByValueAbstractBase {
public void virtualMethod(PassedByValue pbv) {
director_pass_by_value_runme.passByVal = pbv;
}
}

View file

@ -0,0 +1,24 @@
<?php
require "tests.php";
require "director_pass_by_value.php";
$passByVal = null;
class director_pass_by_value_Derived extends DirectorPassByValueAbstractBase {
function virtualMethod($b) {
global $passByVal;
$passByVal = $b;
}
}
# bug was the passByVal global object was destroyed after the call to virtualMethod had finished.
$caller = new Caller();
$caller->call_virtualMethod(new director_pass_by_value_Derived());
$ret = $passByVal->getVal();
if ($ret != 0x12345678) {
check::fail("Bad return value, got " . dechex($ret));
}
check::done();
?>

View file

@ -0,0 +1,13 @@
import director_pass_by_value
passByVal = None
class director_pass_by_value_Derived(director_pass_by_value.DirectorPassByValueAbstractBase):
def virtualMethod(self, b):
global passByVal
passByVal = b
# bug was the passByVal global object was destroyed after the call to virtualMethod had finished.
director_pass_by_value.Caller().call_virtualMethod(director_pass_by_value_Derived())
ret = passByVal.getVal();
if ret != 0x12345678:
raise RuntimeError("Bad return value, got " + hex(ret))

View file

@ -409,8 +409,8 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
#endif
%typemap(directorin) SWIGTYPE
%{ $input = (void *)&$1; %}
%typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, false)"
%{ $input = (void *)new $1_ltype((const $1_ltype &)$1); %}
%typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, true)"
%typemap(csdirectorout) SWIGTYPE "$&csclassname.getCPtr($cscall).Handle"
/* Generic pointers and references */

View file

@ -31,7 +31,7 @@
$*csclassname ret = (cPtr == global::System.IntPtr.Zero) ? null : new $*csclassname(cPtr, $owner);$excode
return ($*csinterfacename)ret;
}
%typemap(csdirectorin) CTYPE "($&csinterfacename)new $&csclassname($iminput, false)"
%typemap(csdirectorin) CTYPE "($&csinterfacename)new $&csclassname($iminput, true)"
%typemap(csdirectorin) CTYPE & "($csinterfacename)new $csclassname($iminput, false)"
%typemap(csdirectorin) CTYPE *, CTYPE [] "($iminput == global::System.IntPtr.Zero) ? null : ($csinterfacename)new $csclassname($iminput, false)"
%typemap(csdirectorin) CTYPE *const& "($iminput == global::System.IntPtr.Zero) ? null : ($*csinterfacename)new $*csclassname($iminput, false)"

View file

@ -57,7 +57,7 @@
#endif
%typemap(directorin) SWIGTYPE
"$input = (void *)&$1;"
"$input = (void *)new $1_ltype((const $1_ltype &)$1);"
%typemap(directorout) SWIGTYPE
%{ if (!$input) {
SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Unexpected null return for type $1_type");
@ -65,7 +65,7 @@
}
$result = *($&1_ltype)$input; %}
%typemap(ddirectorin) SWIGTYPE "new $&dclassname($winput, false)"
%typemap(ddirectorin) SWIGTYPE "new $&dclassname($winput, true)"
%typemap(ddirectorout) SWIGTYPE "$&dclassname.swigGetCPtr($dcall)"
%typemap(din) SWIGTYPE "$&dclassname.swigGetCPtr($dinput)"

View file

@ -584,7 +584,7 @@
%typemap(goout) SWIGTYPE ""
%typemap(directorin) SWIGTYPE
%{ $input = ($&1_ltype)&$1; %}
%{ $input = new $1_ltype((const $1_ltype &)$1); %}
%typemap(godirectorin) SWIGTYPE ""

View file

@ -647,8 +647,8 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
%typemap(directorin,descriptor="L$packagepath/$&javaclassname;") SWIGTYPE
%{ $input = 0;
*(($&1_ltype*)&$input) = &$1; %}
%typemap(javadirectorin) SWIGTYPE "new $&javaclassname($jniinput, false)"
*(($&1_ltype*)&$input) = new $1_ltype((const $1_ltype &)$1); %}
%typemap(javadirectorin) SWIGTYPE "new $&javaclassname($jniinput, true)"
%typemap(javadirectorout) SWIGTYPE "$&javaclassname.getCPtr($javacall)"
/* Generic pointers and references */

View file

@ -31,7 +31,7 @@
return (cPtr == 0) ? null : ($javainterfacename)new $javaclassname(cPtr, $owner);
}
%typemap(javadirectorin) CTYPE "($&javainterfacename)new $&javaclassname($jniinput, false)"
%typemap(javadirectorin) CTYPE "($&javainterfacename)new $&javaclassname($jniinput, true)"
%typemap(javadirectorin) CTYPE & "($javainterfacename)new $javaclassname($jniinput, false)"
%typemap(javadirectorin) CTYPE *, CTYPE [] "($jniinput == 0) ? null : ($javainterfacename)new $javaclassname($jniinput, false)"
%typemap(javadirectorin) CTYPE *const& "($jniinput == 0) ? null : ($*javainterfacename)new $*javaclassname($jniinput, false)"
@ -40,7 +40,7 @@
%typemap(javadirectorout) CTYPE *const& "$javacall.$*interfacename_GetInterfaceCPtr()"
%typemap(directorin,descriptor="L$packagepath/$&javainterfacename;") CTYPE
%{ $input = 0;
*(($&1_ltype*)&$input) = &$1; %}
*(($&1_ltype*)&$input) = new $1_ltype((const $1_ltype &)$1); %}
%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE *, CTYPE []
%{ *(($&1_ltype)&$input) = ($1_ltype) $1; %}
%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE &

View file

@ -429,7 +429,7 @@
%typemap(directorin) SWIGTYPE
{
SWIG_SetPointerZval($input, SWIG_as_voidptr(&$1), $&1_descriptor, 2);
SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&1_descriptor, 1|2);
}
%typemap(out) void "";

View file

@ -415,7 +415,7 @@
}
%typemap(directorin,noblock=1) SWIGTYPE {
$input = SWIG_NewPointerObj(%as_voidptr(&$1), $&descriptor, %newpointer_flags);
$input = SWIG_NewPointerObj(%as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags);
}
%typemap(directorin,noblock=1) SWIGTYPE & {