pidl/python: allocate objects with ref pointers
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Mon, 28 Oct 2019 22:58:32 +0000 (11:58 +1300)
committerNoel Power <npower@samba.org>
Thu, 14 Nov 2019 16:12:40 +0000 (16:12 +0000)
Struct members that are marked as ref pointers need to have an object
allocated for them.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Pair-programmed-with: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Noel Power <npower@samba.org>
pidl/lib/Parse/Pidl/Samba4/Python.pm
selftest/knownfail.d/python-segfaults

index 8d5de31e7bb2f9f4bad77051b5f6ce6436178415..fbb61c33580823869a8462039d66a6d85f11d1f2 100644 (file)
@@ -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("");
index 671de9be4a28a39e113ae642da129c32218a5f99..e100356553dcdd759803b80b47d5b5147406745b 100644 (file)
@@ -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