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