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