]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
pidl:Python: prepare code to avoid NTSTATUS/WERROR exceptions
authorStefan Metzmacher <metze@samba.org>
Tue, 28 Jan 2025 13:56:54 +0000 (14:56 +0100)
committerJule Anger <janger@samba.org>
Mon, 3 Feb 2025 14:53:10 +0000 (14:53 +0000)
They are returned as additional result.

It means callers can look at all out params,
even if the status is an error.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14213

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
(cherry picked from commit 7ecaf1a779370ef3ecf189e51a5e668329fa24c7)

pidl/lib/Parse/Pidl/Samba4/Python.pm

index 6db26cc04dc7d448735f6b32b49264892e25c96e..7a415c99c3abf1676ed265af380a9e5306a69868 100644 (file)
@@ -970,6 +970,7 @@ sub PythonFunctionUnpackOut($$$)
        $self->pidl("static PyObject *$outfnname(struct $fn->{NAME} *r)");
        $self->pidl("{");
        $self->indent;
+       $self->pidl("_UNUSED_ bool raise_result_exception = true;");
        foreach my $e (@{$fn->{ELEMENTS}}) {
                next unless (grep(/out/,@{$e->{DIRECTION}}));
                next if (($metadata_args->{in}->{$e->{NAME}} and grep(/in/, @{$e->{DIRECTION}})) or
@@ -987,7 +988,16 @@ sub PythonFunctionUnpackOut($$$)
                $result_size++;
        }
 
+       my $max_result_size = $result_size;
+       my $alloc_size = "$result_size";
+       if ($fn->{RETURN_TYPE} and $is_raisable_return) {
+               $max_result_size++;
+       }
        $self->pidl("PyObject *result = NULL;");
+       if ($max_result_size != $result_size) {
+               $self->pidl("size_t result_size = $result_size;");
+               $alloc_size = "result_size";
+       }
        $self->pidl("");
 
        if ($result_size > 1) {
@@ -997,24 +1007,39 @@ sub PythonFunctionUnpackOut($$$)
        }
 
        if ($fn->{RETURN_TYPE} and $is_raisable_return) {
+               $self->pidl("if (raise_result_exception) {");
+               $self->indent;
                if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") {
                        $self->handle_ntstatus("r->out.result", "NULL", undef);
                } elsif (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "WERROR") {
                        $self->handle_werror("r->out.result", "NULL", undef);
                }
+               $self->deindent;
+               $self->pidl("} else {");
+               $self->indent;
+               $self->pidl("/* $fn->{RETURN_TYPE} will be part of the results */");
+               $self->pidl("result_size += 1;");
+               $self->deindent;
+               $self->pidl("}");
+               $self->pidl("");
        }
 
-       if ($result_size > 1) {
-               $self->pidl("result = PyTuple_New($result_size);");
+       if ($max_result_size > 1) {
+               if ($max_result_size != $result_size) {
+                       $self->pidl("if (result_size > 1) {");
+                       $self->indent;
+               }
+               $self->pidl("result = PyTuple_New($alloc_size);");
                $self->pidl("if (result == NULL) {");
                $self->indent;
                $self->pidl("return NULL;");
                $self->deindent;
                $self->pidl("}");
+               if ($max_result_size != $result_size) {
+                       $self->deindent;
+                       $self->pidl("}");
+               }
                $self->pidl("");
-       } elsif ($result_size == 0) {
-               $self->pidl("result = Py_None;");
-               $self->pidl("Py_INCREF(result);");
        }
 
        my $i = 0;
@@ -1030,23 +1055,59 @@ sub PythonFunctionUnpackOut($$$)
                                $signature .= $e->{NAME};
                        }
 
-                       if ($result_size > 1) {
+                       if ($max_result_size > 1) {
+                               if ($max_result_size != $result_size and $result_size == 1) {
+                                       $self->pidl("if (result_size > 1) {");
+                                       $self->indent;
+                               }
                                $self->pidl("PyTuple_SetItem(result, $i, $py_name);");
-                               $i++;
-                       } else {
+                               if ($max_result_size != $result_size and $result_size == 1) {
+                                       $self->deindent;
+                                       $self->pidl("}");
+                               }
+                       }
+                       if ($result_size == 1) {
+                               if ($max_result_size != $result_size) {
+                                       $self->pidl("if (result_size == 1) {");
+                                       $self->indent;
+                               }
                                $self->pidl("result = $py_name;");
+                               if ($max_result_size != $result_size) {
+                                       $self->deindent;
+                                       $self->pidl("}");
+                               }
                        }
+                       $self->pidl("");
+                       $i++;
                }
        }
 
-       if ($fn->{RETURN_TYPE} and not $is_raisable_return) {
+       if ($fn->{RETURN_TYPE} and $is_raisable_return) {
+               $self->pidl("if (!raise_result_exception) {");
+               $self->indent;
+       }
+
+       if ($fn->{RETURN_TYPE}) {
                my $conv = $self->ConvertObjectToPythonData("r", $fn->{RETURN_TYPE}, "r->out.result", $fn);
-               if ($result_size > 1) {
+               if ($max_result_size > 1) {
                        $self->pidl("PyTuple_SetItem(result, $i, $conv);");
-               } else {
+               } elsif ($max_result_size == 1) {
                        $self->pidl("result = $conv;");
+               } else {
+                       fatal($fn->{ORIGINAL}, "Internal error max_result_size=$max_result_size");
                }
-               $signature .= "result";
+
+               if (not $is_raisable_return) {
+                       $signature .= "result";
+               }
+       }
+
+       if ($fn->{RETURN_TYPE} and $is_raisable_return) {
+               $self->deindent;
+               $self->pidl("}");
+               $self->pidl("");
+       } elsif ($fn->{RETURN_TYPE}) {
+               $self->pidl("");
        }
 
        if (substr($signature, -2) eq ", ") {
@@ -1056,6 +1117,20 @@ sub PythonFunctionUnpackOut($$$)
                $signature .= ")";
        }
 
+       if ($result_size == 0) {
+               if ($max_result_size != $result_size) {
+                       $self->pidl("if (result_size == 0) {");
+                       $self->indent;
+               }
+               $self->pidl("result = Py_None;");
+               $self->pidl("Py_INCREF(result);");
+               if ($max_result_size != $result_size) {
+                       $self->deindent;
+                       $self->pidl("}");
+               }
+               $self->pidl("");
+       }
+
        $self->pidl("return result;");
        $self->deindent;
        $self->pidl("}");