LCOV - code coverage report
Current view: top level - lib/talloc - pytalloc_util.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 105 144 72.9 %
Date: 2024-04-13 12:30:31 Functions: 17 19 89.5 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Python/Talloc glue
       4             :    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
       5             :    
       6             :      ** NOTE! The following LGPL license applies to the talloc
       7             :      ** library. This does NOT imply that all of Samba is released
       8             :      ** under the LGPL
       9             : 
      10             :    This library is free software; you can redistribute it and/or
      11             :    modify it under the terms of the GNU Lesser General Public
      12             :    License as published by the Free Software Foundation; either
      13             :    version 3 of the License, or (at your option) any later version.
      14             : 
      15             :    This library is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :    Lesser General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU Lesser General Public
      21             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "lib/replace/system/python.h"
      25             : #include "replace.h"
      26             : #include <talloc.h>
      27             : #include "pytalloc.h"
      28             : #include <assert.h>
      29             : #include "pytalloc_private.h"
      30             : 
      31             : static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
      32             :                                          TALLOC_CTX *mem_ctx, void *ptr, bool steal);
      33             : 
      34    83678010 : _PUBLIC_ PyTypeObject *pytalloc_GetObjectType(void)
      35             : {
      36    69546190 :         static PyTypeObject *type = NULL;
      37    69546190 :         PyObject *mod;
      38             : 
      39    83678010 :         mod = PyImport_ImportModule("talloc");
      40    83678010 :         if (mod == NULL) {
      41           0 :                 return NULL;
      42             :         }
      43             : 
      44    83678010 :         type = (PyTypeObject *)PyObject_GetAttrString(mod, "Object");
      45    69546190 :         Py_DECREF(mod);
      46             : 
      47    83678010 :         return type;
      48             : }
      49             : 
      50   254718214 : _PUBLIC_ PyTypeObject *pytalloc_GetBaseObjectType(void)
      51             : {
      52   213057566 :         static PyTypeObject *type = NULL;
      53   213057566 :         PyObject *mod;
      54             : 
      55   254718214 :         mod = PyImport_ImportModule("talloc");
      56   254718214 :         if (mod == NULL) {
      57           0 :                 return NULL;
      58             :         }
      59             : 
      60   254718214 :         type = (PyTypeObject *)PyObject_GetAttrString(mod, "BaseObject");
      61   213057566 :         Py_DECREF(mod);
      62             : 
      63   254718214 :         return type;
      64             : }
      65             : 
      66     5143756 : static PyTypeObject *pytalloc_GetGenericObjectType(void)
      67             : {
      68     4235013 :         static PyTypeObject *type = NULL;
      69     4235013 :         PyObject *mod;
      70             : 
      71     5143756 :         mod = PyImport_ImportModule("talloc");
      72     5143756 :         if (mod == NULL) {
      73           0 :                 return NULL;
      74             :         }
      75             : 
      76     5143756 :         type = (PyTypeObject *)PyObject_GetAttrString(mod, "GenericObject");
      77     4235013 :         Py_DECREF(mod);
      78             : 
      79     5143756 :         return type;
      80             : }
      81             : 
      82             : /**
      83             :  * Import an existing talloc pointer into a Python object.
      84             :  */
      85         130 : _PUBLIC_ PyObject *pytalloc_steal_ex(PyTypeObject *py_type, TALLOC_CTX *mem_ctx,
      86             :                                      void *ptr)
      87             : {
      88         130 :         return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, true);
      89             : }
      90             : 
      91             : /**
      92             :  * Import an existing talloc pointer into a Python object.
      93             :  */
      94    18074625 : _PUBLIC_ PyObject *pytalloc_steal(PyTypeObject *py_type, void *ptr)
      95             : {
      96    18074625 :         return pytalloc_steal_or_reference(py_type, ptr, ptr, true);
      97             : }
      98             : 
      99             : 
     100             : /**
     101             :  * Import an existing talloc pointer into a Python object, leaving the
     102             :  * original parent, and creating a reference to the object in the python
     103             :  * object.
     104             :  *
     105             :  * We remember the object we hold the reference to (a
     106             :  * possibly-non-talloc pointer), the existing parent (typically the
     107             :  * start of the array) and the new referenced parent.  That way we can
     108             :  * cope with the fact that we will have multiple parents, one per time
     109             :  * python sees the object.
     110             :  */
     111    65590569 : _PUBLIC_ PyObject *pytalloc_reference_ex(PyTypeObject *py_type,
     112             :                                          TALLOC_CTX *mem_ctx, void *ptr)
     113             : {
     114    65590569 :         return pytalloc_steal_or_reference(py_type, mem_ctx, ptr, false);
     115             : }
     116             : 
     117             : 
     118             : /**
     119             :  * Internal function that either steals or references the talloc
     120             :  * pointer into a new talloc context.
     121             :  */
     122    83665324 : static PyObject *pytalloc_steal_or_reference(PyTypeObject *py_type,
     123             :                                          TALLOC_CTX *mem_ctx, void *ptr, bool steal)
     124             : {
     125    83665324 :         bool ok = false;
     126    83665324 :         TALLOC_CTX *talloc_ctx = NULL;
     127    83665324 :         bool is_baseobject = false;
     128    83665324 :         PyObject *obj = NULL;
     129    83665324 :         PyTypeObject *BaseObjectType = NULL, *ObjectType = NULL;
     130             : 
     131    83665324 :         BaseObjectType = pytalloc_GetBaseObjectType();
     132    83665324 :         if (BaseObjectType == NULL) {
     133           0 :                 goto err;
     134             :         }
     135    83665324 :         ObjectType = pytalloc_GetObjectType();
     136    83665324 :         if (ObjectType == NULL) {
     137           0 :                 goto err;
     138             :         }
     139             : 
     140             :         /* this should have been tested by caller */
     141    83665324 :         if (mem_ctx == NULL) {
     142           0 :                 return PyErr_NoMemory();
     143             :         }
     144             : 
     145    83665324 :         is_baseobject = PyType_IsSubtype(py_type, BaseObjectType);
     146    83665324 :         if (!is_baseobject) {
     147           9 :                 if (!PyType_IsSubtype(py_type, ObjectType)) {
     148           0 :                         PyErr_SetString(PyExc_TypeError,
     149             :                                 "Expected type based on talloc");
     150           0 :                         return NULL;
     151             :                 }
     152             :         }
     153             : 
     154    83665324 :         obj = py_type->tp_alloc(py_type, 0);
     155    83665324 :         if (obj == NULL) {
     156           0 :                 goto err;
     157             :         }
     158             : 
     159    83665324 :         talloc_ctx = talloc_new(NULL);
     160    83665324 :         if (talloc_ctx == NULL) {
     161           0 :                 PyErr_NoMemory();
     162           0 :                 goto err;
     163             :         }
     164             : 
     165    83665324 :         if (steal) {
     166    18074755 :                 ok = (talloc_steal(talloc_ctx, mem_ctx) != NULL);
     167             :         } else {
     168    65590569 :                 ok = (talloc_reference(talloc_ctx, mem_ctx) != NULL);
     169             :         }
     170    83665324 :         if (!ok) {
     171           0 :                 goto err;
     172             :         }
     173    83665324 :         talloc_set_name_const(talloc_ctx, py_type->tp_name);
     174             : 
     175    83665324 :         if (is_baseobject) {
     176    83665315 :                 pytalloc_BaseObject *ret = (pytalloc_BaseObject*)obj;
     177    83665315 :                 ret->talloc_ctx = talloc_ctx;
     178    83665315 :                 ret->talloc_ptr_ctx = mem_ctx;
     179    83665315 :                 ret->ptr = ptr;
     180             :         } else {
     181           9 :                 pytalloc_Object *ret = (pytalloc_Object*)obj;
     182           9 :                 ret->talloc_ctx = talloc_ctx;
     183           9 :                 ret->ptr = ptr;
     184             :         }
     185    14129695 :         return obj;
     186             : 
     187           0 : err:
     188           0 :         TALLOC_FREE(talloc_ctx);
     189           0 :         Py_XDECREF(obj);
     190           0 :         return NULL;
     191             : }
     192             : 
     193             : /*
     194             :  * Wrap a generic talloc pointer into a talloc.GenericObject,
     195             :  * this is a subclass of talloc.BaseObject.
     196             :  */
     197         130 : _PUBLIC_ PyObject *pytalloc_GenericObject_steal_ex(TALLOC_CTX *mem_ctx, void *ptr)
     198             : {
     199         130 :         PyTypeObject *tp = pytalloc_GetGenericObjectType();
     200         130 :         return pytalloc_steal_ex(tp, mem_ctx, ptr);
     201             : }
     202             : 
     203             : /*
     204             :  * Wrap a generic talloc pointer into a talloc.GenericObject,
     205             :  * this is a subclass of talloc.BaseObject.
     206             :  */
     207     5143626 : _PUBLIC_ PyObject *pytalloc_GenericObject_reference_ex(TALLOC_CTX *mem_ctx, void *ptr)
     208             : {
     209     5143626 :         PyTypeObject *tp = pytalloc_GetGenericObjectType();
     210     5143626 :         return pytalloc_reference_ex(tp, mem_ctx, ptr);
     211             : }
     212             : 
     213          31 : _PUBLIC_ int pytalloc_Check(PyObject *obj)
     214             : {
     215          31 :         PyTypeObject *tp = pytalloc_GetObjectType();
     216             : 
     217          31 :         return PyObject_TypeCheck(obj, tp);
     218             : }
     219             : 
     220   170984041 : _PUBLIC_ int pytalloc_BaseObject_check(PyObject *obj)
     221             : {
     222   170984041 :         PyTypeObject *tp = pytalloc_GetBaseObjectType();
     223             : 
     224   170984041 :         return PyObject_TypeCheck(obj, tp);
     225             : }
     226             : 
     227     5561476 : _PUBLIC_ size_t pytalloc_BaseObject_size(void)
     228             : {
     229     5561476 :         return sizeof(pytalloc_BaseObject);
     230             : }
     231             : 
     232      686464 : static void *_pytalloc_get_checked_type(PyObject *py_obj, const char *type_name,
     233             :                                         bool check_only, const char *function)
     234             : {
     235      482262 :         TALLOC_CTX *mem_ctx;
     236      686464 :         void *ptr = NULL;
     237      482262 :         void *type_obj;
     238             : 
     239      686464 :         mem_ctx = _pytalloc_get_mem_ctx(py_obj);
     240      686464 :         ptr = _pytalloc_get_ptr(py_obj);
     241             : 
     242      686464 :         if (mem_ctx != ptr || ptr == NULL) {
     243           0 :                 if (check_only) {
     244           0 :                         return NULL;
     245             :                 }
     246             : 
     247           0 :                 PyErr_Format(PyExc_TypeError, "%s: expected %s, "
     248             :                              "but the pointer is no talloc pointer, "
     249             :                              "pytalloc_get_ptr() would get the raw pointer.",
     250             :                              function, type_name);
     251           0 :                 return NULL;
     252             :         }
     253             : 
     254      686464 :         type_obj = talloc_check_name(ptr, type_name);
     255      686464 :         if (type_obj == NULL) {
     256           0 :                 const char *name = NULL;
     257             : 
     258           0 :                 if (check_only) {
     259           0 :                         return NULL;
     260             :                 }
     261             : 
     262           0 :                 name = talloc_get_name(ptr);
     263           0 :                 PyErr_Format(PyExc_TypeError, "%s: expected %s, got %s",
     264             :                              function, type_name, name);
     265           0 :                 return NULL;
     266             :         }
     267             : 
     268      204202 :         return ptr;
     269             : }
     270             : 
     271           0 : _PUBLIC_ int _pytalloc_check_type(PyObject *py_obj, const char *type_name)
     272             : {
     273           0 :         void *ptr = NULL;
     274             : 
     275           0 :         ptr = _pytalloc_get_checked_type(py_obj, type_name,
     276             :                                          true, /* check_only */
     277             :                                          "pytalloc_check_type");
     278           0 :         if (ptr == NULL) {
     279           0 :                 return 0;
     280             :         }
     281             : 
     282           0 :         return 1;
     283             : }
     284             : 
     285      686464 : _PUBLIC_ void *_pytalloc_get_type(PyObject *py_obj, const char *type_name)
     286             : {
     287      686464 :         return _pytalloc_get_checked_type(py_obj, type_name,
     288             :                                           false, /* not check_only */
     289             :                                           "pytalloc_get_type");
     290             : }
     291             : 
     292   146079625 : _PUBLIC_ void *_pytalloc_get_ptr(PyObject *py_obj)
     293             : {
     294   146079625 :         if (pytalloc_BaseObject_check(py_obj)) {
     295   146079598 :                 return ((pytalloc_BaseObject *)py_obj)->ptr;
     296             :         }
     297          27 :         if (pytalloc_Check(py_obj)) {
     298          27 :                 return ((pytalloc_Object *)py_obj)->ptr;
     299             :         }
     300           0 :         return NULL;
     301             : }
     302             : 
     303    24904416 : _PUBLIC_ TALLOC_CTX *_pytalloc_get_mem_ctx(PyObject *py_obj)
     304             : {
     305    24904416 :         if (pytalloc_BaseObject_check(py_obj)) {
     306    24904412 :                 return ((pytalloc_BaseObject *)py_obj)->talloc_ptr_ctx;
     307             :         }
     308           4 :         if (pytalloc_Check(py_obj)) {
     309           2 :                 return ((pytalloc_Object *)py_obj)->talloc_ctx;
     310             :         }
     311           1 :         return NULL;
     312             : }
     313             : 
     314       68840 : _PUBLIC_ int pytalloc_BaseObject_PyType_Ready(PyTypeObject *type)
     315             : {
     316       68840 :         PyTypeObject *talloc_type = pytalloc_GetBaseObjectType();
     317       68840 :         if (talloc_type == NULL) {
     318           0 :                 return -1;
     319             :         }
     320             : 
     321       68840 :         type->tp_base = talloc_type;
     322       68840 :         type->tp_basicsize = pytalloc_BaseObject_size();
     323             : 
     324       68840 :         return PyType_Ready(type);
     325             : }
     326             : 
     327           0 : _PUBLIC_ const char *_pytalloc_get_name(PyObject *obj)
     328             : {
     329           0 :         void *ptr = pytalloc_get_ptr(obj);
     330           0 :         if (ptr == NULL) {
     331           0 :                 return "non-talloc object";
     332             :         }
     333           0 :         return talloc_get_name(ptr);
     334             : }

Generated by: LCOV version 1.14