From a86c5f7cae7ec9a3398300555a0b644689d946a1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 19 Sep 2024 06:14:53 +0200 Subject: Merging upstream version 4.4.0. Signed-off-by: Daniel Baumann --- tools/pidl/lib/Parse/Pidl/Samba4/Python.pm | 403 +++++++++++++++++------------ 1 file changed, 243 insertions(+), 160 deletions(-) (limited to 'tools/pidl/lib/Parse/Pidl/Samba4/Python.pm') diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm b/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm index f418ac48..d7ccf830 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -4,11 +4,10 @@ # released under the GNU GPL package Parse::Pidl::Samba4::Python; - -use Exporter; -@ISA = qw(Exporter); +use parent Parse::Pidl::Base; use strict; +use warnings; use Parse::Pidl qw(warning fatal error); use Parse::Pidl::Typelist qw(hasType resolveType getType mapTypeName expandAlias bitmap_type_fn enum_type_fn); use Parse::Pidl::Util qw(has_property ParseExpr unmake_str); @@ -17,6 +16,7 @@ use Parse::Pidl::CUtil qw(get_value_of get_pointer_to); use Parse::Pidl::Samba4 qw(ArrayDynamicallyAllocated); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv); + use vars qw($VERSION); $VERSION = '0.01'; @@ -34,41 +34,11 @@ sub new($) { bless($self, $class); } -sub pidl_hdr ($$) -{ - my $self = shift; - $self->{res_hdr} .= shift; -} - -sub pidl($$) -{ - my ($self, $d) = @_; - if ($d) { - if ((!($d =~ /^#/))) { - $self->{res} .= $self->{tabs}; - } - $self->{res} .= $d; - } - $self->{res} .= "\n"; -} - -sub indent($) -{ - my ($self) = @_; - $self->{tabs} .= "\t"; -} - -sub deindent($) -{ - my ($self) = @_; - $self->{tabs} = substr($self->{tabs}, 0, -1); -} - sub PrettifyTypeName($$) { my ($name, $basename) = @_; - $basename =~ s/^.*\.([^.]+)$/\1/; + $basename =~ s/^.*\.([^.]+)$/$1/; $name =~ s/^$basename\_//; @@ -83,7 +53,7 @@ sub Import foreach (@imports) { $_ = unmake_str($_); s/\.idl$//; - $self->pidl_hdr("#include \"librpc/gen_ndr/$_\.h\"\n"); + $self->pidl_hdr("#include \"librpc/gen_ndr/$_\.h\""); $self->register_module_import("samba.dcerpc.$_"); } } @@ -199,8 +169,16 @@ sub PythonElementGetSet($$$$$$) { $self->pidl("static PyObject *py_$name\_get_$e->{NAME}(PyObject *obj, void *closure)"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(obj);"); + $self->pidl("$cname *object = pytalloc_get_ptr(obj);"); $self->pidl("PyObject *py_$e->{NAME};"); + my $l = $e->{LEVELS}[0]; + if ($l->{TYPE} eq "POINTER") { + $self->pidl("if ($varname == NULL) {"); + $self->indent; + $self->pidl("Py_RETURN_NONE;"); + $self->deindent; + $self->pidl("}"); + } $self->ConvertObjectToPython("pytalloc_get_mem_ctx(obj)", $env, $e, $varname, "py_$e->{NAME}", "return NULL;"); $self->pidl("return py_$e->{NAME};"); $self->deindent; @@ -210,9 +188,8 @@ sub PythonElementGetSet($$$$$$) { $self->pidl("static int py_$name\_set_$e->{NAME}(PyObject *py_obj, PyObject *value, void *closure)"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"); + $self->pidl("$cname *object = pytalloc_get_ptr(py_obj);"); my $mem_ctx = "pytalloc_get_mem_ctx(py_obj)"; - my $l = $e->{LEVELS}[0]; my $nl = GetNextLevel($e, $l); if ($l->{TYPE} eq "POINTER" and not ($nl->{TYPE} eq "ARRAY" and ($nl->{IS_FIXED} or is_charset_array($e, $nl))) and @@ -279,10 +256,10 @@ sub PythonStruct($$$$$$) # If the struct is not public there ndr_pull/ndr_push functions will # be static so not callable from here if (has_property($d, "public")) { - $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj)"); + $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"); + $self->pidl("$cname *object = pytalloc_get_ptr(py_obj);"); $self->pidl("PyObject *ret = NULL;"); $self->pidl("DATA_BLOB blob;"); $self->pidl("enum ndr_err_code err;"); @@ -312,8 +289,8 @@ sub PythonStruct($$$$$$) $self->pidl("static PyObject *py_$name\_ndr_unpack(PyObject *py_obj, PyObject *args, PyObject *kwargs)"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"); - $self->pidl("DATA_BLOB blob;"); + $self->pidl("$cname *object = pytalloc_get_ptr(py_obj);"); + $self->pidl("DATA_BLOB blob = {.data = NULL, .length = 0};"); $self->pidl("Py_ssize_t blob_length = 0;"); $self->pidl("enum ndr_err_code err;"); $self->pidl("const char * const kwnames[] = { \"data_blob\", \"allow_remaining\", NULL };"); @@ -359,15 +336,15 @@ sub PythonStruct($$$$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj)"); + $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"); + $self->pidl("$cname *object = pytalloc_get_ptr(py_obj);"); $self->pidl("PyObject *ret;"); $self->pidl("char *retstr;"); $self->pidl(""); $self->pidl("retstr = ndr_print_struct_string(pytalloc_get_mem_ctx(py_obj), (ndr_print_fn_t)ndr_print_$name, \"$name\", object);"); - $self->pidl("ret = PyStr_FromString(retstr);"); + $self->pidl("ret = PyUnicode_FromString(retstr);"); $self->pidl("talloc_free(retstr);"); $self->pidl(""); $self->pidl("return ret;"); @@ -379,7 +356,7 @@ sub PythonStruct($$$$$$) $self->pidl("static PyMethodDef $py_methods\[] = {"); $self->indent; $self->pidl("{ \"__ndr_pack__\", (PyCFunction)py_$name\_ndr_pack, METH_NOARGS, \"S.ndr_pack(object) -> blob\\nNDR pack\" },"); - $self->pidl("{ \"__ndr_unpack__\", (PyCFunction)py_$name\_ndr_unpack, METH_VARARGS|METH_KEYWORDS, \"S.ndr_unpack(class, blob, allow_remaining=False) -> None\\nNDR unpack\" },"); + $self->pidl("{ \"__ndr_unpack__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_unpack), METH_VARARGS|METH_KEYWORDS, \"S.ndr_unpack(class, blob, allow_remaining=False) -> None\\nNDR unpack\" },"); $self->pidl("{ \"__ndr_print__\", (PyCFunction)py_$name\_ndr_print, METH_NOARGS, \"S.ndr_print(object) -> None\\nNDR print\" },"); $self->pidl("{ NULL, NULL, 0, NULL }"); $self->deindent; @@ -387,7 +364,7 @@ sub PythonStruct($$$$$$) $self->pidl(""); } - $self->pidl_hdr("static PyTypeObject $name\_Type;\n"); + $self->pidl_hdr("static PyTypeObject $name\_Type;"); $self->pidl(""); my $docstring = $self->DocString($d, $name); my $typeobject = "$name\_Type"; @@ -491,7 +468,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. + # These 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 structure 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(""); @@ -499,19 +531,19 @@ sub PythonFunctionStruct($$$$) my $py_methods = "NULL"; my $ndr_call = "const struct ndr_interface_call *call = NULL;"; - my $object_ptr = "$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"; + my $object_ptr = "$cname *object = pytalloc_get_ptr(py_obj);"; - $self->pidl("static PyObject *py_$name\_ndr_opnum(PyTypeObject *type)"); + $self->pidl("static PyObject *py_$name\_ndr_opnum(PyTypeObject *type, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; $self->pidl(""); $self->pidl(""); - $self->pidl("return PyInt_FromLong($fn->{OPNUM});"); + $self->pidl("return PyLong_FromLong($fn->{OPNUM});"); $self->deindent; $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj, int ndr_inout_flags, uint32_t ndr_push_flags)"); + $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj, ndr_flags_type ndr_inout_flags, libndr_flags ndr_push_flags)"); $self->pidl("{"); $self->indent; $self->pidl("$ndr_call"); @@ -562,7 +594,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("const char * const kwnames[] = { \"bigendian\", \"ndr64\", NULL };"); $self->pidl("PyObject *bigendian_obj = NULL;"); $self->pidl("PyObject *ndr64_obj = NULL;"); - $self->pidl("uint32_t ndr_push_flags = 0;"); + $self->pidl("libndr_flags ndr_push_flags = 0;"); $self->pidl(""); $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"|OO:__ndr_pack_in__\","); $self->indent; @@ -597,7 +629,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("const char * const kwnames[] = { \"bigendian\", \"ndr64\", NULL };"); $self->pidl("PyObject *bigendian_obj = NULL;"); $self->pidl("PyObject *ndr64_obj = NULL;"); - $self->pidl("uint32_t ndr_push_flags = 0;"); + $self->pidl("libndr_flags ndr_push_flags = 0;"); $self->pidl(""); $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"|OO:__ndr_pack_out__\","); $self->indent; @@ -626,7 +658,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_unpack(PyObject *py_obj, const DATA_BLOB *blob, int ndr_inout_flags, uint32_t ndr_pull_flags, bool allow_remaining)"); + $self->pidl("static PyObject *py_$name\_ndr_unpack(PyObject *py_obj, const DATA_BLOB *blob, ndr_flags_type ndr_inout_flags, libndr_flags ndr_pull_flags, bool allow_remaining)"); $self->pidl("{"); $self->indent; $self->pidl("$ndr_call"); @@ -703,7 +735,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("const char * const kwnames[] = { \"data_blob\", \"bigendian\", \"ndr64\", \"allow_remaining\", NULL };"); $self->pidl("PyObject *bigendian_obj = NULL;"); $self->pidl("PyObject *ndr64_obj = NULL;"); - $self->pidl("uint32_t ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); + $self->pidl("libndr_flags ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); $self->pidl("PyObject *allow_remaining_obj = NULL;"); $self->pidl("bool allow_remaining = false;"); $self->pidl(""); @@ -751,7 +783,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("const char * const kwnames[] = { \"data_blob\", \"bigendian\", \"ndr64\", \"allow_remaining\", NULL };"); $self->pidl("PyObject *bigendian_obj = NULL;"); $self->pidl("PyObject *ndr64_obj = NULL;"); - $self->pidl("uint32_t ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); + $self->pidl("libndr_flags ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); $self->pidl("PyObject *allow_remaining_obj = NULL;"); $self->pidl("bool allow_remaining = false;"); $self->pidl(""); @@ -791,7 +823,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj, const char *name, int ndr_inout_flags)"); + $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj, const char *name, ndr_flags_type ndr_inout_flags)"); $self->pidl("{"); $self->indent; $self->pidl("$ndr_call"); @@ -809,7 +841,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("call = &ndr_table_$iface\.calls[$fn->{OPNUM}];"); $self->pidl(""); $self->pidl("retstr = ndr_print_function_string(pytalloc_get_mem_ctx(py_obj), call->ndr_print, name, ndr_inout_flags, object);"); - $self->pidl("ret = PyStr_FromString(retstr);"); + $self->pidl("ret = PyUnicode_FromString(retstr);"); $self->pidl("TALLOC_FREE(retstr);"); $self->pidl(""); $self->pidl("return ret;"); @@ -817,7 +849,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_print_in(PyObject *py_obj)"); + $self->pidl("static PyObject *py_$name\_ndr_print_in(PyObject *py_obj, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; $self->pidl("return py_$name\_ndr_print(py_obj, \"$name\_in\", NDR_IN);"); @@ -825,7 +857,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_print_out(PyObject *py_obj)"); + $self->pidl("static PyObject *py_$name\_ndr_print_out(PyObject *py_obj, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; $self->pidl("return py_$name\_ndr_print(py_obj, \"$name\_out\", NDR_OUT);"); @@ -840,19 +872,19 @@ sub PythonFunctionStruct($$$$) $self->indent; $self->pidl("\"$modulename.$prettyname.opnum() -> ".sprintf("%d (0x%02x)", $fn->{OPNUM}, $fn->{OPNUM})." \" },"); $self->deindent; - $self->pidl("{ \"__ndr_pack_in__\", (PyCFunction)py_$name\_ndr_pack_in, METH_VARARGS|METH_KEYWORDS,"); + $self->pidl("{ \"__ndr_pack_in__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_pack_in), METH_VARARGS|METH_KEYWORDS,"); $self->indent; $self->pidl("\"S.ndr_pack_in(object, bigendian=False, ndr64=False) -> blob\\nNDR pack input\" },"); $self->deindent; - $self->pidl("{ \"__ndr_pack_out__\", (PyCFunction)py_$name\_ndr_pack_out, METH_VARARGS|METH_KEYWORDS,"); + $self->pidl("{ \"__ndr_pack_out__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_pack_out), METH_VARARGS|METH_KEYWORDS,"); $self->indent; $self->pidl("\"S.ndr_pack_out(object, bigendian=False, ndr64=False) -> blob\\nNDR pack output\" },"); $self->deindent; - $self->pidl("{ \"__ndr_unpack_in__\", (PyCFunction)py_$name\_ndr_unpack_in, METH_VARARGS|METH_KEYWORDS,"); + $self->pidl("{ \"__ndr_unpack_in__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_unpack_in), METH_VARARGS|METH_KEYWORDS,"); $self->indent; $self->pidl("\"S.ndr_unpack_in(class, blob, bigendian=False, ndr64=False, allow_remaining=False) -> None\\nNDR unpack input\" },"); $self->deindent; - $self->pidl("{ \"__ndr_unpack_out__\", (PyCFunction)py_$name\_ndr_unpack_out, METH_VARARGS|METH_KEYWORDS,"); + $self->pidl("{ \"__ndr_unpack_out__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_unpack_out), METH_VARARGS|METH_KEYWORDS,"); $self->indent; $self->pidl("\"S.ndr_unpack_out(class, blob, bigendian=False, ndr64=False, allow_remaining=False) -> None\\nNDR unpack output\" },"); $self->deindent; @@ -863,7 +895,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("};"); $self->pidl(""); - $self->pidl_hdr("static PyTypeObject $name\_Type;\n"); + $self->pidl_hdr("static PyTypeObject $name\_Type;"); $self->pidl(""); my $docstring = $self->DocString($fn, $name); my $typeobject = "$name\_Type"; @@ -1235,7 +1267,7 @@ sub PythonType($$$$) $self->pidl("PyObject *in = NULL;"); $self->pidl("$typename *out = NULL;"); $self->pidl(""); - $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"OiO:import\","); + $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"OiO:export\","); $self->indent; $self->pidl("discard_const_p(char *, kwnames),"); $self->pidl("&mem_ctx_obj,"); @@ -1269,12 +1301,12 @@ sub PythonType($$$$) $py_methods = "py_$d->{NAME}_methods"; $self->pidl("static PyMethodDef $py_methods\[] = {"); $self->indent; - $self->pidl("{ \"__import__\", (PyCFunction)py_$d->{NAME}\_import,"); + $self->pidl("{ \"__import__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$d->{NAME}\_import),"); $self->indent; $self->pidl("METH_VARARGS|METH_KEYWORDS|METH_CLASS,"); $self->pidl("\"T.__import__(mem_ctx, level, in) => ret.\" },"); $self->deindent; - $self->pidl("{ \"__export__\", (PyCFunction)py_$d->{NAME}\_export,"); + $self->pidl("{ \"__export__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$d->{NAME}\_export),"); $self->indent; $self->pidl("METH_VARARGS|METH_KEYWORDS|METH_CLASS,"); $self->pidl("\"T.__export__(mem_ctx, level, in) => ret.\" },"); @@ -1294,7 +1326,7 @@ sub PythonType($$$$) $self->pidl(""); $self->pidl(""); - $self->pidl_hdr("static PyTypeObject $typeobject;\n"); + $self->pidl_hdr("static PyTypeObject $typeobject;"); $self->pidl("static PyTypeObject $typeobject = {"); $self->indent; $self->pidl("PyVarObject_HEAD_INIT(NULL, 0)"); @@ -1349,7 +1381,7 @@ sub Interface($$$) } if (defined $interface->{PROPERTIES}->{uuid}) { - $self->pidl_hdr("static PyTypeObject $interface->{NAME}_InterfaceType;\n"); + $self->pidl_hdr("static PyTypeObject $interface->{NAME}_InterfaceType;"); $self->pidl(""); my @fns = (); @@ -1387,7 +1419,7 @@ sub Interface($$$) my ($infn, $outfn, $callfn, $prettyname, $docstring, $opnum) = @$d; $self->pidl("{ \"$prettyname\", $docstring, (py_dcerpc_call_fn)$callfn, (py_data_pack_fn)$infn, (py_data_unpack_fn)$outfn, $opnum, &ndr_table_$interface->{NAME} },"); } - $self->pidl("{ NULL }"); + $self->pidl("{0}"); $self->deindent; $self->pidl("};"); $self->pidl(""); @@ -1446,9 +1478,9 @@ sub Interface($$$) $self->pidl(""); - my $signature = "\"$interface->{NAME}_abstract_syntax()\\n\""; + $signature = "\"$interface->{NAME}_abstract_syntax()\\n\""; - my $docstring = $self->DocString($interface, $interface->{NAME}."_syntax"); + $docstring = $self->DocString($interface, $interface->{NAME}."_syntax"); if ($docstring) { $docstring = "$signature$docstring"; @@ -1482,7 +1514,7 @@ sub Interface($$$) ""]); } - $self->pidl_hdr("\n"); + $self->pidl_hdr(""); } sub register_module_method($$$$$) @@ -1635,7 +1667,6 @@ sub ConvertStringFromPythonData($$$$$) $self->pidl("unicode = PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\");"); $self->pidl("if (unicode == NULL) {"); $self->indent; - $self->pidl("PyErr_NoMemory();"); $self->pidl("$fail"); $self->deindent; $self->pidl("}"); @@ -1669,6 +1700,27 @@ sub ConvertStringFromPythonData($$$$$) $self->pidl("}"); } +sub ConvertU16StringFromPythonData($$$$$) +{ + my ($self, $mem_ctx, $py_var, $target, $fail) = @_; + + $self->pidl("{"); + $self->indent; + $self->pidl("unsigned char *str = NULL;"); + $self->pidl(""); + $self->pidl("str = PyUtf16String_FromBytes("); + $self->pidl(" $mem_ctx, $py_var);"); + $self->pidl("if (str == NULL) {"); + $self->indent; + $self->pidl("$fail"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("$target = str;"); + $self->deindent; + $self->pidl("}"); +} + sub ConvertObjectFromPythonData($$$$$$;$$) { my ($self, $mem_ctx, $cvar, $ctype, $target, $fail, $location, $switch) = @_; @@ -1715,21 +1767,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->pidl("}"); $self->pidl("if (test_var > uint_max) {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range 0 - %llu, got %llu\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, uint_max, test_var);"); - $self->pidl($fail); - $self->deindent; - $self->pidl("}"); - $self->pidl("$target = test_var;"); - $self->deindent; - $self->pidl("} else if (PyInt_Check($cvar)) {"); - $self->indent; - $self->pidl("long test_var;"); - $self->pidl("test_var = PyInt_AsLong($cvar);"); - $self->pidl("if (test_var < 0 || test_var > uint_max) {"); - $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range 0 - %llu, got %ld\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, uint_max, test_var);"); + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s within range 0 - %llu, got %llu\","); + $self->pidl(" PyLong_Type.tp_name, uint_max, test_var);"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1737,8 +1776,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->deindent; $self->pidl("} else {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s or %s\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name);"); + $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s\","); + $self->pidl(" PyLong_Type.tp_name);"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1767,21 +1806,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->pidl("}"); $self->pidl("if (test_var < int_min || test_var > int_max) {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range %lld - %lld, got %lld\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max, test_var);"); - $self->pidl($fail); - $self->deindent; - $self->pidl("}"); - $self->pidl("$target = test_var;"); - $self->deindent; - $self->pidl("} else if (PyInt_Check($cvar)) {"); - $self->indent; - $self->pidl("long test_var;"); - $self->pidl("test_var = PyInt_AsLong($cvar);"); - $self->pidl("if (test_var < int_min || test_var > int_max) {"); - $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range %lld - %lld, got %ld\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max, test_var);"); + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s within range %lld - %lld, got %lld\","); + $self->pidl(" PyLong_Type.tp_name, int_min, int_max, test_var);"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1789,8 +1815,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->deindent; $self->pidl("} else {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s or %s\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name);"); + $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s\","); + $self->pidl(" PyLong_Type.tp_name);"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1803,7 +1829,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) my $ctype_name = $self->use_type_variable($ctype); unless (defined ($ctype_name)) { error($location, "Unable to determine origin of type `" . mapTypeName($ctype) . "'"); - $self->pidl("PyErr_SetString(PyExc_TypeError, \"Can not convert C Type " . mapTypeName($ctype) . " from Python\");"); + $self->pidl("PyErr_SetString(PyExc_TypeError, \"Cannot convert Python object to NDR $target\");"); + $self->pidl("$fail"); return; } $self->pidl("PY_CHECK_TYPE($ctype_name, $cvar, $fail);"); @@ -1849,18 +1876,24 @@ sub ConvertObjectFromPythonData($$$$$$;$$) return; } + if ($actual_ctype->{TYPE} eq "SCALAR" and + $actual_ctype->{NAME} eq "u16string") { + $self->ConvertU16StringFromPythonData($mem_ctx, $cvar, $target, $fail); + return; + } + if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") { - $self->pidl("$target = NT_STATUS(PyInt_AsLong($cvar));"); + $self->pidl("$target = NT_STATUS(PyLong_AsLong($cvar));"); return; } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") { - $self->pidl("$target = W_ERROR(PyInt_AsLong($cvar));"); + $self->pidl("$target = W_ERROR(PyLong_AsLong($cvar));"); return; } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "HRESULT") { - $self->pidl("$target = HRES_ERROR(PyInt_AsLong($cvar));"); + $self->pidl("$target = HRES_ERROR(PyLong_AsLong($cvar));"); return; } @@ -1893,8 +1926,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) if ($recurse == 0) { $self->pidl("if ($py_var == NULL) {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_AttributeError, \"Cannot delete NDR object: " . - mapTypeName($var_name) . "\");"); + $self->pidl("PyErr_Format(PyExc_AttributeError, \"Cannot delete NDR object: $var_name\");"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1902,6 +1934,9 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) $recurse = $recurse + 1; if ($l->{TYPE} eq "POINTER") { + my $need_deindent = 0; + my $need_deref = 0; + if ($l->{POINTER_TYPE} ne "ref") { $self->pidl("if ($py_var == Py_None) {"); $self->indent; @@ -1909,10 +1944,13 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) $self->deindent; $self->pidl("} else {"); $self->indent; + $need_deindent = 1; + if ($nl->{TYPE} eq "POINTER") { + $need_deref = 1; + } } - # if we want to handle more than one level of pointer in python interfaces - # then this is where we would need to allocate it - if ($l->{POINTER_TYPE} eq "ref") { + + if ($l->{POINTER_TYPE} eq "ref" or $need_deref == 1) { $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);"); $self->pidl("if ($var_name == NULL) {"); $self->indent; @@ -1932,11 +1970,20 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) } else { $self->pidl("$var_name = NULL;"); } + if ($need_deref == 1) { + my $ndr_pointer_typename = $self->import_type_variable("samba.dcerpc.base", "ndr_pointer"); + $self->pidl("$py_var = py_dcerpc_ndr_pointer_deref($ndr_pointer_typename, $py_var);"); + $self->pidl("if ($py_var == NULL) {"); + $self->indent; + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + } unless ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) { $var_name = get_value_of($var_name); } $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail, $recurse); - if ($l->{POINTER_TYPE} ne "ref") { + if ($need_deindent == 1) { $self->deindent; $self->pidl("}"); } @@ -1955,7 +2002,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) $self->pidl("int $counter;"); if (ArrayDynamicallyAllocated($e, $l)) { $self->pidl("$var_name = talloc_array_ptrtype($mem_ctx, $var_name, PyList_GET_SIZE($py_var));"); - $self->pidl("if (!$var_name) { $fail; }"); + $self->pidl("if (!$var_name) { $fail }"); $self->pidl("talloc_set_name_const($var_name, \"ARRAY: $var_name\");"); } else { $self->pidl("if (ARRAY_SIZE($var_name) != PyList_GET_SIZE($py_var)) {"); @@ -1967,7 +2014,11 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) } $self->pidl("for ($counter = 0; $counter < PyList_GET_SIZE($py_var); $counter++) {"); $self->indent; - $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GET_ITEM($py_var, $counter)", $e, $nl, $var_name."[$counter]", $fail, 0); + if (ArrayDynamicallyAllocated($e, $l)) { + $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GET_ITEM($py_var, $counter)", $e, $nl, "($var_name)"."[$counter]", $fail, 0); + } else { + $self->ConvertObjectFromPythonLevel($env, $mem_ctx, "PyList_GET_ITEM($py_var, $counter)", $e, $nl, "($var_name)"."[$counter]", $fail, 0); + } $self->deindent; $self->pidl("}"); $self->deindent; @@ -2015,15 +2066,15 @@ sub ConvertScalarToPython($$$$) $ctypename = expandAlias($ctypename); if ($ctypename =~ /^(int64|dlong)$/) { - return "ndr_PyLong_FromLongLong($cvar)"; + return "PyLong_FromLongLong($cvar)"; } if ($ctypename =~ /^(uint64|hyper|NTTIME_hyper|NTTIME|NTTIME_1sec|udlong|udlongr|uid_t|gid_t)$/) { - return "ndr_PyLong_FromUnsignedLongLong($cvar)"; + return "PyLong_FromUnsignedLongLong($cvar)"; } if ($ctypename =~ /^(char|int|int8|int16|int32|time_t)$/) { - return "PyInt_FromLong($cvar)"; + return "PyLong_FromLong($cvar)"; } # Needed to ensure unsigned values in a 32 or 16 bit enum is @@ -2031,11 +2082,11 @@ sub ConvertScalarToPython($$$$) # possibly 64 bit unsigned long. (enums are signed in C, # unsigned in NDR) if ($ctypename =~ /^(uint32|uint3264)$/) { - return "ndr_PyLong_FromUnsignedLongLong((uint32_t)$cvar)"; + return "PyLong_FromUnsignedLongLong((uint32_t)($cvar))"; } if ($ctypename =~ /^(uint|uint8|uint16|uint1632)$/) { - return "PyInt_FromLong((uint16_t)$cvar)"; + return "PyLong_FromLong((uint16_t)($cvar))"; } if ($ctypename eq "DATA_BLOB") { @@ -2062,6 +2113,10 @@ sub ConvertScalarToPython($$$$) return "PyString_FromStringOrNULL($cvar)"; } + if ($ctypename eq "u16string") { + return "PyBytes_FromUtf16StringOrNULL($cvar)"; + } + # Not yet supported if ($ctypename eq "string_array") { return "pytalloc_GenericObject_reference_ex($mem_ctx, $cvar)"; @@ -2138,6 +2193,10 @@ sub ConvertObjectToPythonLevel($$$$$$$) } if ($l->{TYPE} eq "POINTER") { + my $need_wrap = 0; + if ($l->{POINTER_TYPE} ne "ref" and $nl->{TYPE} eq "POINTER") { + $need_wrap = 1; + } if ($l->{POINTER_TYPE} ne "ref") { if ($recurse == 0) { $self->pidl("if ($var_name == NULL) {"); @@ -2164,6 +2223,19 @@ sub ConvertObjectToPythonLevel($$$$$$$) $self->deindent; $self->pidl("}"); } + if ($need_wrap) { + my $py_var_wrap = undef; + $need_wrap = 1; + $self->pidl("{"); + $self->indent; + $py_var_wrap = "py_$e->{NAME}_level_$l->{LEVEL_INDEX}"; + $self->pidl("PyObject *$py_var_wrap = $py_var;"); + my $ndr_pointer_typename = $self->import_type_variable("samba.dcerpc.base", "ndr_pointer"); + $self->pidl("$py_var = py_dcerpc_ndr_pointer_wrap($ndr_pointer_typename, $py_var_wrap);"); + $self->pidl("Py_XDECREF($py_var_wrap);"); + $self->deindent; + $self->pidl("}"); + } } elsif ($l->{TYPE} eq "ARRAY") { if ($pl && $pl->{TYPE} eq "POINTER") { $var_name = get_pointer_to($var_name); @@ -2199,7 +2271,11 @@ sub ConvertObjectToPythonLevel($$$$$$$) $self->indent; my $member_var = "py_$e->{NAME}_$l->{LEVEL_INDEX}"; $self->pidl("PyObject *$member_var;"); - $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name."[$counter]", $member_var, $fail, $recurse); + if (ArrayDynamicallyAllocated($e, $l)) { + $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, "($var_name)"."[$counter]", $member_var, $fail, $recurse); + } else { + $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, $nl, "($var_name)"."[$counter]", $member_var, $fail, $recurse); + } $self->pidl("PyList_SetItem($py_var, $counter, $member_var);"); $self->deindent; $self->pidl("}"); @@ -2219,6 +2295,10 @@ sub ConvertObjectToPythonLevel($$$$$$$) } my $conv = $self->ConvertObjectToPythonData($mem_ctx, $l->{DATA_TYPE}, $var_name, $e->{ORIGINAL}); $self->pidl("$py_var = $conv;"); + if ($conv eq "NULL") { + $self->pidl("PyErr_SetString(PyExc_NotImplementedError, \"Cannot convert NDR $var_name to Python\");"); + $self->pidl("$fail"); + } } elsif ($l->{TYPE} eq "SUBCONTEXT") { $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, $nl, $var_name, $py_var, $fail, $recurse); } else { @@ -2240,18 +2320,36 @@ sub Parse($$$$$) $self->{BASENAME} = $basename; + my $ndr_hdr_include = ""; + if (defined($ndr_hdr)) { + $ndr_hdr_include = "#include \"$ndr_hdr\""; + } $self->pidl_hdr(" /* Python wrapper functions auto-generated by pidl */ #define PY_SSIZE_T_CLEAN 1 /* We use Py_ssize_t for PyArg_ParseTupleAndKeywords */ -#include +#include \"lib/replace/system/python.h\" #include \"python/py3compat.h\" #include \"includes.h\" +#include \"python/modules.h\" #include #include \"librpc/rpc/pyrpc.h\" #include \"librpc/rpc/pyrpc_util.h\" #include \"$hdr\" -#include \"$ndr_hdr\" +$ndr_hdr_include +/* + * Suppress compiler warnings if the generated code does not call these + * functions + */ +#ifndef _MAYBE_UNUSED_ +#ifdef __has_attribute +#if __has_attribute(unused) +#define _MAYBE_UNUSED_ __attribute__ ((unused)) +#else +#define _MAYBE_UNUSED_ +#endif +#endif +#endif /* * These functions are here to ensure they can be optimized out by * the compiler based on the constant input values @@ -2273,7 +2371,7 @@ static inline unsigned long long ndr_sizeof2uintmax(size_t var_size) return 0; } -static inline long long ndr_sizeof2intmax(size_t var_size) +static inline _MAYBE_UNUSED_ long long ndr_sizeof2intmax(size_t var_size) { switch (var_size) { case 8: @@ -2288,25 +2386,6 @@ static inline long long ndr_sizeof2intmax(size_t var_size) return 0; } - -static inline PyObject *ndr_PyLong_FromLongLong(long long v) -{ - if (v > LONG_MAX || v < LONG_MIN) { - return PyLong_FromLongLong(v); - } else { - return PyInt_FromLong(v); - } -} - -static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) -{ - if (v > LONG_MAX) { - return PyLong_FromUnsignedLongLong(v); - } else { - return PyInt_FromLong(v); - } -} - "); foreach my $x (@$ndr) { @@ -2340,9 +2419,9 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("MODULE_INIT_FUNC($basename)"); $self->pidl("{"); $self->indent; - $self->pidl("PyObject *m;"); + $self->pidl("PyObject *m = NULL;"); foreach my $h (@{$self->{module_imports}}) { - $self->pidl("PyObject *$h->{'key'};"); + $self->pidl("PyObject *$h->{'key'} = NULL;"); } $self->pidl(""); @@ -2351,20 +2430,20 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) my $module_path = $h->{'val'}; $self->pidl("$var_name = PyImport_ImportModule(\"$module_path\");"); $self->pidl("if ($var_name == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); } foreach my $h (@{$self->{type_imports}}) { my $type_var = "$h->{'key'}\_Type"; my $module_path = $h->{'val'}; - $self->pidl_hdr("static PyTypeObject *$type_var;\n"); + $self->pidl_hdr("static PyTypeObject *$type_var;"); my $pretty_name = PrettifyTypeName($h->{'key'}, $module_path); my $module_var = "dep_$module_path"; $module_var =~ s/\./_/g; $self->pidl("$type_var = (PyTypeObject *)PyObject_GetAttrString($module_var, \"$pretty_name\");"); $self->pidl("if ($type_var == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); } @@ -2372,7 +2451,7 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) foreach (@{$self->{ready_types}}) { $self->pidl("if (PyType_Ready($_) < 0)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); } $self->pidl($_) foreach (@{$self->{postreadycode}}); @@ -2388,16 +2467,16 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("m = PyModule_Create(&moduledef);"); $self->pidl("if (m == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); foreach my $h (@{$self->{constants}}) { my $pretty_name = PrettifyTypeName($h->{'key'}, $basename); my $py_obj; my ($ctype, $cvar) = @{$h->{'val'}}; if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) { - $py_obj = "ndr_PyLong_FromUnsignedLongLong($cvar)"; + $py_obj = "PyLong_FromUnsignedLongLong($cvar)"; } elsif ($cvar =~ /^".*"$/) { - $py_obj = "PyStr_FromString($cvar)"; + $py_obj = "PyUnicode_FromString($cvar)"; } else { $py_obj = $self->ConvertObjectToPythonData("NULL", expandAlias($ctype), $cvar, undef); } @@ -2414,7 +2493,11 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("#ifdef PY_MOD_".uc($basename)."_PATCH"); $self->pidl("PY_MOD_".uc($basename)."_PATCH(m);"); $self->pidl("#endif"); - + $self->pidl("out:"); + foreach my $h (@{$self->{module_imports}}) { + my $mod_var = $h->{'key'}; + $self->pidl("Py_XDECREF($mod_var);"); + } $self->pidl("return m;"); $self->pidl(""); $self->deindent; -- cgit v1.2.3