From 1261894ecaebc1a3340c42e818be25caa69f6364 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Tue, 29 Oct 2019 11:58:32 +1300 Subject: pidl/python: allocate objects with ref pointers Struct members that are marked as ref pointers need to have an object allocated for them. Signed-off-by: Douglas Bagnall Pair-programmed-with: Andrew Bartlett Signed-off-by: Andrew Bartlett Reviewed-by: Noel Power --- pidl/lib/Parse/Pidl/Samba4/Python.pm | 57 ++++++++++++++++++++++++++++++++++- selftest/knownfail.d/python-segfaults | 2 -- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index 8d5de31e7bb..fbb61c33580 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -499,7 +499,62 @@ sub PythonFunctionStruct($$$$) $self->pidl("static PyObject *py_$name\_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)"); $self->pidl("{"); $self->indent; - $self->pidl("return pytalloc_new($cname, type);"); + + # This creates a new, zeroed C structure and python object. + # Thse may not be valid or sensible values, but this is as + # well as we can do. + + $self->pidl("PyObject *self = pytalloc_new($cname, type);"); + + # If there are any children that are ref pointers, we need to + # allocate something for them to point to just as the pull + # routine will when parsing the stucture from NDR. + # + # We then make those pointers point to zeroed memory + # + # A ref pointer is a pointer in the C structure but a scalar + # on the wire. It is for a remote function like: + # + # int foo(int *i) + # + # This may be called with the pointer by reference eg foo(&i) + # + # That is why this only goes as far as the next level; deeply + # nested pointer chains will end in a NULL. + + my @ref_elements; + foreach my $e (@{$fn->{ELEMENTS}}) { + if (has_property($e, "ref") && ! has_property($e, "charset")) { + if (!has_property($e, 'in') && !has_property($e, 'out')) { + die "ref pointer that is not in or out"; + } + push @ref_elements, $e; + } + } + if (@ref_elements) { + $self->pidl("$cname *_self = ($cname *)pytalloc_get_ptr(self);"); + $self->pidl("TALLOC_CTX *mem_ctx = pytalloc_get_mem_ctx(self);"); + foreach my $e (@ref_elements) { + my $ename = $e->{NAME}; + my $t = mapTypeName($e->{TYPE}); + my $p = $e->{ORIGINAL}->{POINTERS} // 1; + if ($p > 1) { + $self->pidl("/* a pointer to a NULL pointer */"); + $t .= ' ' . '*' x ($p - 1); + } + + # We checked in the loop above that each ref + # pointer is in or out (or both) + if (has_property($e, 'in')) { + $self->pidl("_self->in.$ename = talloc_zero(mem_ctx, $t);"); + } + + if (has_property($e, 'out')) { + $self->pidl("_self->out.$ename = talloc_zero(mem_ctx, $t);"); + } + } + } + $self->pidl("return self;"); $self->deindent; $self->pidl("}"); $self->pidl(""); diff --git a/selftest/knownfail.d/python-segfaults b/selftest/knownfail.d/python-segfaults index 671de9be4a2..e100356553d 100644 --- a/selftest/knownfail.d/python-segfaults +++ b/selftest/knownfail.d/python-segfaults @@ -1,4 +1,2 @@ samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_net_replicate_init__3 -samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dcerpc_idl_ref_elements -samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dcerpc_idl_unixinfo_elements samba.tests.segfault.samba.tests.segfault.SegfaultTests.test_dcerpc_idl_inline_arrays -- cgit v1.2.1