summaryrefslogtreecommitdiff
path: root/pidl
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2016-04-21 21:44:56 +1200
committerAndrew Bartlett <abartlet@samba.org>2016-05-10 01:43:15 +0200
commitf6c79072ca50e05a68b73a80a0ebd635a9bac068 (patch)
treeab53473b3bc73a98cb533ed7d4e71716c427c61f /pidl
parent9e2c1f72e00cf63da777a515b95ed63139ef2d11 (diff)
downloadsamba-f6c79072ca50e05a68b73a80a0ebd635a9bac068.tar.gz
pidl: Correct string handling to use talloc and be in common
The previous string handling assumed the python variables referenced by PyString_AS_STRING had infinite life. When they were re-used the C structure started to point at unexpected things. We now check correctly for Unicode in every case, and we always duplicate the string with talloc_strdup() Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Diffstat (limited to 'pidl')
-rw-r--r--pidl/lib/Parse/Pidl/Samba4/Python.pm103
1 files changed, 61 insertions, 42 deletions
diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm
index 6488ac9c73b..9e39167eb7e 100644
--- a/pidl/lib/Parse/Pidl/Samba4/Python.pm
+++ b/pidl/lib/Parse/Pidl/Samba4/Python.pm
@@ -960,6 +960,55 @@ sub assign($$$)
}
}
+sub ConvertStringFromPythonData($$$$$)
+{
+ my ($self, $mem_ctx, $py_var, $target, $fail) = @_;
+
+ $self->pidl("{");
+ $self->indent;
+ $self->pidl("const char *test_str;");
+ $self->pidl("const char *talloc_str;");
+ $self->pidl("PyObject *unicode = NULL;");
+ $self->pidl("if (PyUnicode_Check($py_var)) {");
+ $self->indent;
+ # FIXME: Use Unix charset setting rather than utf-8
+ $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("}");
+
+ $self->pidl("test_str = PyString_AS_STRING(unicode);");
+ $self->deindent;
+ $self->pidl("} else if (PyString_Check($py_var)) {");
+ $self->indent;
+ $self->pidl("test_str = PyString_AS_STRING($py_var);");
+ $self->deindent;
+ $self->pidl("} else {");
+ $self->indent;
+ $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected string or unicode object, got %s\", Py_TYPE($py_var)->tp_name);");
+ $self->pidl("$fail");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("talloc_str = talloc_strdup($mem_ctx, test_str);");
+ $self->pidl("if (unicode != NULL) {");
+ $self->indent;
+ $self->pidl("Py_DECREF(unicode);");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("if (talloc_str == NULL) {");
+ $self->indent;
+ $self->pidl("PyErr_NoMemory();");
+ $self->pidl("$fail");
+ $self->deindent;
+ $self->pidl("}");
+ $self->pidl("$target = talloc_str;");
+ $self->deindent;
+ $self->pidl("}");
+}
+
sub ConvertObjectFromPythonData($$$$$$;$)
{
my ($self, $mem_ctx, $cvar, $ctype, $target, $fail, $location) = @_;
@@ -1114,33 +1163,17 @@ sub ConvertObjectFromPythonData($$$$$$;$)
}
if ($actual_ctype->{TYPE} eq "SCALAR" and
- ($actual_ctype->{NAME} eq "string" or $actual_ctype->{NAME} eq "nbt_string" or $actual_ctype->{NAME} eq "nbt_name" or $actual_ctype->{NAME} eq "wrepl_nbt_name")) {
- $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AS_STRING($cvar));");
- return;
- }
-
- if ($actual_ctype->{TYPE} eq "SCALAR" and ($actual_ctype->{NAME} eq "dns_string" or $actual_ctype->{NAME} eq "dns_name")) {
- $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AS_STRING($cvar));");
- return;
- }
-
- if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") {
- $self->pidl("$target = PyString_AS_STRING($cvar);");
- return;
- }
-
- if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv6address") {
- $self->pidl("$target = PyString_AsString($cvar);");
- return;
- }
-
- if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "dnsp_name") {
- $self->pidl("$target = PyString_AS_STRING($cvar);");
- return;
- }
-
- if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "dnsp_string") {
- $self->pidl("$target = PyString_AS_STRING($cvar);");
+ ($actual_ctype->{NAME} eq "string"
+ or $actual_ctype->{NAME} eq "nbt_string"
+ or $actual_ctype->{NAME} eq "nbt_name"
+ or $actual_ctype->{NAME} eq "wrepl_nbt_name"
+ or $actual_ctype->{NAME} eq "dns_string"
+ or $actual_ctype->{NAME} eq "dnsp_string"
+ or $actual_ctype->{NAME} eq "dns_name"
+ or $actual_ctype->{NAME} eq "ipv4address"
+ or $actual_ctype->{NAME} eq "ipv6address"
+ or $actual_ctype->{NAME} eq "dnsp_name")) {
+ $self->ConvertStringFromPythonData($mem_ctx, $cvar, $target, $fail);
return;
}
@@ -1218,21 +1251,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$)
}
if (is_charset_array($e, $l)) {
- $self->pidl("if (PyUnicode_Check($py_var)) {");
- $self->indent;
- # FIXME: Use Unix charset setting rather than utf-8
- $self->pidl($var_name . " = PyString_AS_STRING(PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\"));");
- $self->deindent;
- $self->pidl("} else if (PyString_Check($py_var)) {");
- $self->indent;
- $self->pidl($var_name . " = PyString_AS_STRING($py_var);");
- $self->deindent;
- $self->pidl("} else {");
- $self->indent;
- $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected string or unicode object, got %s\", Py_TYPE($py_var)->tp_name);");
- $self->pidl("$fail");
- $self->deindent;
- $self->pidl("}");
+ $self->ConvertStringFromPythonData($mem_ctx, $py_var, $var_name, $fail);
} else {
my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}";
$self->pidl("PY_CHECK_TYPE(&PyList_Type, $py_var, $fail);");