pidl/Python: generate a ndr_PyLong_AsCheckedUnsignedLongLong() 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:12 +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 570e8675eda3ffcecf34470eeac27408d1bd1c10..20830f809f082b05bffb5c67bead52b37142877b 100644 (file)
@@ -1750,45 +1750,14 @@ sub ConvertObjectFromPythonData($$$$$$;$$)
                                |uid_t|gid_t)$/x) {
                $self->pidl("{");
                $self->indent;
-               $self->pidl("const unsigned long long uint_max = ndr_sizeof2uintmax(sizeof($target));");
-               $self->pidl("if (PyLong_Check($cvar)) {");
-               $self->indent;
-               $self->pidl("unsigned long long test_var;");
-               $self->pidl("test_var = PyLong_AsUnsignedLongLong($cvar);");
+               $self->pidl("unsigned long long ull_value;");
+               $self->pidl("ull_value = ndr_PyLong_AsCheckedUnsignedLongLong($cvar, sizeof($target));");
                $self->pidl("if (PyErr_Occurred() != NULL) {");
                $self->indent;
                $self->pidl($fail);
                $self->deindent;
                $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 || (unsigned long long)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($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) . ")ull_value;");
                $self->deindent;
                $self->pidl("}");
                return;
@@ -2391,6 +2360,62 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v)
        }
 }
 
+/*
+ * This is the unsigned Python Integer -> C integer validation
+ * case. The signed case is below.
+ */
+static inline unsigned long long ndr_PyLong_AsCheckedUnsignedLongLong(PyObject *py_value,
+                                                                     size_t target_size)
+{
+       const unsigned long long uint_max = ndr_sizeof2uintmax(target_size);
+       unsigned long long ret_value = 0;
+
+       if (PyLong_Check(py_value)) {
+               unsigned long long test_var;
+
+               test_var = PyLong_AsUnsignedLongLong(py_value);
+               if (PyErr_Occurred() != NULL) {
+                       return 0;
+               }
+
+               if (test_var > uint_max) {
+                       PyErr_Format(PyExc_OverflowError,
+                                    \"Expected type %s or %s within range 0 - %llu, got %llu\",
+                                    PyInt_Type.tp_name, PyLong_Type.tp_name, uint_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 (PyErr_Occurred() != NULL) {
+                       return 0;
+               }
+
+               if (test_var < 0 || (unsigned long long)test_var > uint_max) {
+                       PyErr_Format(PyExc_OverflowError,
+                                    \"Expected type %s or %s within range 0 - %llu, got %ld\",
+                                    PyInt_Type.tp_name, PyLong_Type.tp_name, uint_max, test_var);
+                       return 0;
+               }
+
+               ret_value = test_var;
+
+               return ret_value;
+       }
+
+       PyErr_Format(PyExc_TypeError,
+                    \"Expected type %s or %s within range 0 - %llu\",
+                    PyInt_Type.tp_name, PyLong_Type.tp_name, uint_max);
+       return 0;
+}
+
 ");
 
        foreach my $x (@$ndr) {