1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

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>
This commit is contained in:
Andrew Bartlett 2016-04-21 21:44:56 +12:00
parent 9e2c1f72e0
commit f6c79072ca

View File

@ -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);");