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