pidl/Python: generate a ndr_PyLong_AsCheckedLongLong() helper function
authorStefan Metzmacher <metze@samba.org>
Tue, 9 May 2017 07:59:39 +0000 (09:59 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 18 Feb 2019 11:55:14 +0000 (12:55 +0100)
This reduces the size of the generated C code a lot.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
pidl/lib/Parse/Pidl/Samba4/Python.pm

index 20830f809f082b05bffb5c67bead52b37142877b..1eaf8e7a9d0c78af5d6df5ab2d780c214f0ec4a4 100644 (file)
@@ -1770,46 +1770,14 @@ sub ConvertObjectFromPythonData($$$$$$;$$)
        if ($ctype_alias  =~ /^(dlong|char|int[0-9]*|time_t)$/x) {
                $self->pidl("{");
                $self->indent;
-               $self->pidl("const long long int_max = ndr_sizeof2intmax(sizeof($target));");
-               $self->pidl("const long long int_min = -int_max - 1;");
-               $self->pidl("if (PyLong_Check($cvar)) {");
-               $self->indent;
-               $self->pidl("long long test_var;");
-               $self->pidl("test_var = PyLong_AsLongLong($cvar);");
+               $self->pidl("long long ll_value;");
+               $self->pidl("ll_value = ndr_PyLong_AsCheckedLongLong($cvar, sizeof($target));");
                $self->pidl("if (PyErr_Occurred() != NULL) {");
                $self->indent;
                $self->pidl($fail);
                $self->deindent;
                $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($fail);
-               $self->deindent;
-               $self->pidl("}");
-               $self->pidl("$target = test_var;");
-               $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($fail);
-               $self->deindent;
-               $self->pidl("}");
+               $self->pidl("$target = (" . mapTypeName($ctype_alias) . ")ll_value;");
                $self->deindent;
                $self->pidl("}");
                return;
@@ -2416,6 +2384,62 @@ static inline unsigned long long ndr_PyLong_AsCheckedUnsignedLongLong(PyObject *
        return 0;
 }
 
+
+/*
+ * Confirm the signed python integer fits in the C type
+ * correctly.  It is subtly different from the unsigned case
+ * above, so while it looks like a duplicate, it is not
+ * actually a duplicate.
+ */
+static inline long long ndr_PyLong_AsCheckedLongLong(PyObject *py_value,
+                                                    size_t target_size)
+{
+       const long long int_max = ndr_sizeof2intmax(target_size);
+       const long long int_min = -int_max - 1;
+       long long ret_value;
+
+       if (PyLong_Check(py_value)) {
+               long long test_var;
+
+               test_var = PyLong_AsLongLong(py_value);
+               if (PyErr_Occurred() != NULL) {
+                       return 0;
+               }
+
+               if (test_var < int_min || test_var > int_max) {
+                       PyErr_Format(PyExc_OverflowError,
+                                    \"Expected type %s or %s within range %lld - %lld, got %lld\",
+                                    PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max, test_var);
+                       return 0;
+               }
+
+               ret_value = test_var;
+
+               return ret_value;
+       }
+
+       if (PyInt_Check(py_value)) {
+               long test_var;
+
+               test_var = PyInt_AsLong(py_value);
+               if (test_var < int_min || test_var > int_max) {
+                       PyErr_Format(PyExc_OverflowError,
+                                    \"Expected type %s or %s within range %lld - %lld, got %ld\",
+                                    PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max, test_var);
+                       return 0;
+               }
+
+               ret_value = test_var;
+
+               return ret_value;
+       }
+
+       PyErr_Format(PyExc_TypeError,
+                    \"Expected type %s or %s within range %lld - %lld\",
+                    PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max);
+       return 0;
+}
+
 ");
 
        foreach my $x (@$ndr) {