Branch data Line data Source code
1 : : 2 : : /* Map C struct members to Python object attributes */ 3 : : 4 : : #include "Python.h" 5 : : #include "structmember.h" // PyMemberDef 6 : : 7 : : PyObject * 8 : 131735 : PyMember_GetOne(const char *obj_addr, PyMemberDef *l) 9 : : { 10 : : PyObject *v; 11 : : 12 : 131735 : const char* addr = obj_addr + l->offset; 13 [ + - - - : 131735 : switch (l->type) { - + + - - - - - - - - + + - - - - ] 14 : 36 : case T_BOOL: 15 : 36 : v = PyBool_FromLong(*(char*)addr); 16 : 36 : break; 17 : 0 : case T_BYTE: 18 : 0 : v = PyLong_FromLong(*(char*)addr); 19 : 0 : break; 20 : 0 : case T_UBYTE: 21 : 0 : v = PyLong_FromUnsignedLong(*(unsigned char*)addr); 22 : 0 : break; 23 : 0 : case T_SHORT: 24 : 0 : v = PyLong_FromLong(*(short*)addr); 25 : 0 : break; 26 : 0 : case T_USHORT: 27 : 0 : v = PyLong_FromUnsignedLong(*(unsigned short*)addr); 28 : 0 : break; 29 : 20 : case T_INT: 30 : 20 : v = PyLong_FromLong(*(int*)addr); 31 : 20 : break; 32 : 1341 : case T_UINT: 33 : 1341 : v = PyLong_FromUnsignedLong(*(unsigned int*)addr); 34 : 1341 : break; 35 : 0 : case T_LONG: 36 : 0 : v = PyLong_FromLong(*(long*)addr); 37 : 0 : break; 38 : 0 : case T_ULONG: 39 : 0 : v = PyLong_FromUnsignedLong(*(unsigned long*)addr); 40 : 0 : break; 41 : 0 : case T_PYSSIZET: 42 : 0 : v = PyLong_FromSsize_t(*(Py_ssize_t*)addr); 43 : 0 : break; 44 : 0 : case T_FLOAT: 45 : 0 : v = PyFloat_FromDouble((double)*(float*)addr); 46 : 0 : break; 47 : 0 : case T_DOUBLE: 48 : 0 : v = PyFloat_FromDouble(*(double*)addr); 49 : 0 : break; 50 : 0 : case T_STRING: 51 [ # # ]: 0 : if (*(char**)addr == NULL) { 52 : 0 : v = Py_NewRef(Py_None); 53 : : } 54 : : else 55 : 0 : v = PyUnicode_FromString(*(char**)addr); 56 : 0 : break; 57 : 0 : case T_STRING_INPLACE: 58 : 0 : v = PyUnicode_FromString((char*)addr); 59 : 0 : break; 60 : 0 : case T_CHAR: 61 : 0 : v = PyUnicode_FromStringAndSize((char*)addr, 1); 62 : 0 : break; 63 : 130178 : case T_OBJECT: 64 : 130178 : v = *(PyObject **)addr; 65 [ - + ]: 130178 : if (v == NULL) 66 : 0 : v = Py_None; 67 : 130178 : Py_INCREF(v); 68 : 130178 : break; 69 : 160 : case T_OBJECT_EX: 70 : 160 : v = *(PyObject **)addr; 71 [ + + ]: 160 : if (v == NULL) { 72 : 81 : PyObject *obj = (PyObject *)obj_addr; 73 : 81 : PyTypeObject *tp = Py_TYPE(obj); 74 : 81 : PyErr_Format(PyExc_AttributeError, 75 : : "'%.200s' object has no attribute '%s'", 76 : : tp->tp_name, l->name); 77 : : } 78 : 160 : Py_XINCREF(v); 79 : 160 : break; 80 : 0 : case T_LONGLONG: 81 : 0 : v = PyLong_FromLongLong(*(long long *)addr); 82 : 0 : break; 83 : 0 : case T_ULONGLONG: 84 : 0 : v = PyLong_FromUnsignedLongLong(*(unsigned long long *)addr); 85 : 0 : break; 86 : 0 : case T_NONE: 87 : 0 : v = Py_NewRef(Py_None); 88 : 0 : break; 89 : 0 : default: 90 : 0 : PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); 91 : 0 : v = NULL; 92 : : } 93 : 131735 : return v; 94 : : } 95 : : 96 : : #define WARN(msg) \ 97 : : do { \ 98 : : if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \ 99 : : return -1; \ 100 : : } while (0) 101 : : 102 : : int 103 : 19888 : PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) 104 : : { 105 : : PyObject *oldv; 106 : : 107 : 19888 : addr += l->offset; 108 : : 109 [ - + ]: 19888 : if ((l->flags & READONLY)) 110 : : { 111 : 0 : PyErr_SetString(PyExc_AttributeError, "readonly attribute"); 112 : 0 : return -1; 113 : : } 114 [ - + ]: 19888 : if (v == NULL) { 115 [ # # ]: 0 : if (l->type == T_OBJECT_EX) { 116 : : /* Check if the attribute is set. */ 117 [ # # ]: 0 : if (*(PyObject **)addr == NULL) { 118 : 0 : PyErr_SetString(PyExc_AttributeError, l->name); 119 : 0 : return -1; 120 : : } 121 : : } 122 [ # # ]: 0 : else if (l->type != T_OBJECT) { 123 : 0 : PyErr_SetString(PyExc_TypeError, 124 : : "can't delete numeric/char attribute"); 125 : 0 : return -1; 126 : : } 127 : : } 128 [ + - - - : 19888 : switch (l->type) { - - - - - - - - + - - - - - ] 129 : 75 : case T_BOOL:{ 130 [ - + ]: 75 : if (!PyBool_Check(v)) { 131 : 0 : PyErr_SetString(PyExc_TypeError, 132 : : "attribute value type must be bool"); 133 : 0 : return -1; 134 : : } 135 [ + - ]: 75 : if (v == Py_True) 136 : 75 : *(char*)addr = (char) 1; 137 : : else 138 : 0 : *(char*)addr = (char) 0; 139 : 75 : break; 140 : : } 141 : 0 : case T_BYTE:{ 142 : 0 : long long_val = PyLong_AsLong(v); 143 [ # # # # ]: 0 : if ((long_val == -1) && PyErr_Occurred()) 144 : 0 : return -1; 145 : 0 : *(char*)addr = (char)long_val; 146 : : /* XXX: For compatibility, only warn about truncations 147 : : for now. */ 148 [ # # # # ]: 0 : if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN)) 149 [ # # ]: 0 : WARN("Truncation of value to char"); 150 : 0 : break; 151 : : } 152 : 0 : case T_UBYTE:{ 153 : 0 : long long_val = PyLong_AsLong(v); 154 [ # # # # ]: 0 : if ((long_val == -1) && PyErr_Occurred()) 155 : 0 : return -1; 156 : 0 : *(unsigned char*)addr = (unsigned char)long_val; 157 [ # # # # ]: 0 : if ((long_val > UCHAR_MAX) || (long_val < 0)) 158 [ # # ]: 0 : WARN("Truncation of value to unsigned char"); 159 : 0 : break; 160 : : } 161 : 0 : case T_SHORT:{ 162 : 0 : long long_val = PyLong_AsLong(v); 163 [ # # # # ]: 0 : if ((long_val == -1) && PyErr_Occurred()) 164 : 0 : return -1; 165 : 0 : *(short*)addr = (short)long_val; 166 [ # # # # ]: 0 : if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN)) 167 [ # # ]: 0 : WARN("Truncation of value to short"); 168 : 0 : break; 169 : : } 170 : 0 : case T_USHORT:{ 171 : 0 : long long_val = PyLong_AsLong(v); 172 [ # # # # ]: 0 : if ((long_val == -1) && PyErr_Occurred()) 173 : 0 : return -1; 174 : 0 : *(unsigned short*)addr = (unsigned short)long_val; 175 [ # # # # ]: 0 : if ((long_val > USHRT_MAX) || (long_val < 0)) 176 [ # # ]: 0 : WARN("Truncation of value to unsigned short"); 177 : 0 : break; 178 : : } 179 : 0 : case T_INT:{ 180 : 0 : long long_val = PyLong_AsLong(v); 181 [ # # # # ]: 0 : if ((long_val == -1) && PyErr_Occurred()) 182 : 0 : return -1; 183 : 0 : *(int *)addr = (int)long_val; 184 [ # # # # ]: 0 : if ((long_val > INT_MAX) || (long_val < INT_MIN)) 185 [ # # ]: 0 : WARN("Truncation of value to int"); 186 : 0 : break; 187 : : } 188 : 0 : case T_UINT:{ 189 : 0 : unsigned long ulong_val = PyLong_AsUnsignedLong(v); 190 [ # # # # ]: 0 : if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) { 191 : : /* XXX: For compatibility, accept negative int values 192 : : as well. */ 193 : 0 : PyErr_Clear(); 194 : 0 : ulong_val = PyLong_AsLong(v); 195 [ # # # # ]: 0 : if ((ulong_val == (unsigned long)-1) && 196 : 0 : PyErr_Occurred()) 197 : 0 : return -1; 198 : 0 : *(unsigned int *)addr = (unsigned int)ulong_val; 199 [ # # ]: 0 : WARN("Writing negative value into unsigned field"); 200 : : } else 201 : 0 : *(unsigned int *)addr = (unsigned int)ulong_val; 202 [ # # ]: 0 : if (ulong_val > UINT_MAX) 203 [ # # ]: 0 : WARN("Truncation of value to unsigned int"); 204 : 0 : break; 205 : : } 206 : 0 : case T_LONG:{ 207 : 0 : *(long*)addr = PyLong_AsLong(v); 208 [ # # # # ]: 0 : if ((*(long*)addr == -1) && PyErr_Occurred()) 209 : 0 : return -1; 210 : 0 : break; 211 : : } 212 : 0 : case T_ULONG:{ 213 : 0 : *(unsigned long*)addr = PyLong_AsUnsignedLong(v); 214 [ # # ]: 0 : if ((*(unsigned long*)addr == (unsigned long)-1) 215 [ # # ]: 0 : && PyErr_Occurred()) { 216 : : /* XXX: For compatibility, accept negative int values 217 : : as well. */ 218 : 0 : PyErr_Clear(); 219 : 0 : *(unsigned long*)addr = PyLong_AsLong(v); 220 [ # # ]: 0 : if ((*(unsigned long*)addr == (unsigned long)-1) 221 [ # # ]: 0 : && PyErr_Occurred()) 222 : 0 : return -1; 223 [ # # ]: 0 : WARN("Writing negative value into unsigned field"); 224 : : } 225 : 0 : break; 226 : : } 227 : 0 : case T_PYSSIZET:{ 228 : 0 : *(Py_ssize_t*)addr = PyLong_AsSsize_t(v); 229 [ # # ]: 0 : if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1) 230 [ # # ]: 0 : && PyErr_Occurred()) 231 : 0 : return -1; 232 : 0 : break; 233 : : } 234 : 0 : case T_FLOAT:{ 235 : 0 : double double_val = PyFloat_AsDouble(v); 236 [ # # # # ]: 0 : if ((double_val == -1) && PyErr_Occurred()) 237 : 0 : return -1; 238 : 0 : *(float*)addr = (float)double_val; 239 : 0 : break; 240 : : } 241 : 0 : case T_DOUBLE: 242 : 0 : *(double*)addr = PyFloat_AsDouble(v); 243 [ # # # # ]: 0 : if ((*(double*)addr == -1) && PyErr_Occurred()) 244 : 0 : return -1; 245 : 0 : break; 246 : 19813 : case T_OBJECT: 247 : : case T_OBJECT_EX: 248 : 19813 : oldv = *(PyObject **)addr; 249 : 19813 : *(PyObject **)addr = Py_XNewRef(v); 250 : 19813 : Py_XDECREF(oldv); 251 : 19813 : break; 252 : 0 : case T_CHAR: { 253 : : const char *string; 254 : : Py_ssize_t len; 255 : : 256 : 0 : string = PyUnicode_AsUTF8AndSize(v, &len); 257 [ # # # # ]: 0 : if (string == NULL || len != 1) { 258 : 0 : PyErr_BadArgument(); 259 : 0 : return -1; 260 : : } 261 : 0 : *(char*)addr = string[0]; 262 : 0 : break; 263 : : } 264 : 0 : case T_STRING: 265 : : case T_STRING_INPLACE: 266 : 0 : PyErr_SetString(PyExc_TypeError, "readonly attribute"); 267 : 0 : return -1; 268 : 0 : case T_LONGLONG:{ 269 : : long long value; 270 : 0 : *(long long*)addr = value = PyLong_AsLongLong(v); 271 [ # # # # ]: 0 : if ((value == -1) && PyErr_Occurred()) 272 : 0 : return -1; 273 : 0 : break; 274 : : } 275 : 0 : case T_ULONGLONG:{ 276 : : unsigned long long value; 277 : : /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong 278 : : doesn't ??? */ 279 [ # # ]: 0 : if (PyLong_Check(v)) 280 : 0 : *(unsigned long long*)addr = value = PyLong_AsUnsignedLongLong(v); 281 : : else 282 : 0 : *(unsigned long long*)addr = value = PyLong_AsLong(v); 283 [ # # # # ]: 0 : if ((value == (unsigned long long)-1) && PyErr_Occurred()) 284 : 0 : return -1; 285 : 0 : break; 286 : : } 287 : 0 : default: 288 : 0 : PyErr_Format(PyExc_SystemError, 289 : : "bad memberdescr type for %s", l->name); 290 : 0 : return -1; 291 : : } 292 : 19888 : return 0; 293 : : }