this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <cstdarg>
3#include <cwchar>
4
5#include "cpython-data.h"
6#include "cpython-types.h"
7
8#include "api-handle.h"
9#include "handles.h"
10#include "modsupport-internal.h"
11#include "module-builtins.h"
12#include "objects.h"
13#include "runtime.h"
14
15namespace py {
16
17PY_EXPORT int PyModule_AddObject(PyObject* pymodule, const char* name,
18 PyObject* obj) {
19 Thread* thread = Thread::current();
20 HandleScope scope(thread);
21 Runtime* runtime = thread->runtime();
22
23 Object module_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(pymodule)));
24 if (!runtime->isInstanceOfModule(*module_obj)) {
25 thread->raiseWithFmt(LayoutId::kTypeError,
26 "PyModule_AddObject() needs module as first arg");
27 return -1;
28 }
29 if (name == nullptr) {
30 // TODO(cshapiro): throw a TypeError
31 return -1;
32 }
33 Object name_obj(&scope, Runtime::internStrFromCStr(thread, name));
34 Module module(&scope, *module_obj);
35 Object value(&scope, ApiHandle::stealReference(obj));
36 moduleAtPut(thread, module, name_obj, value);
37 return 0;
38}
39
40PY_EXPORT int PyModule_AddIntConstant(PyObject* m, const char* name,
41 long value) {
42 PyObject* o = PyLong_FromLong(value);
43 if (!o) return -1;
44 if (PyModule_AddObject(m, name, o) == 0) return 0;
45 Py_DECREF(o);
46 return -1;
47}
48
49PY_EXPORT int PyModule_AddStringConstant(PyObject* pymodule, const char* name,
50 const char* value) {
51 PyObject* str = PyUnicode_FromString(value);
52 if (!str) return -1;
53 if (PyModule_AddObject(pymodule, name, str) == 0) return 0;
54 Py_DECREF(str);
55 return -1;
56}
57
58static PyObject* doMakeTuple(const char**, std::va_list*, char, Py_ssize_t,
59 int);
60static PyObject* doMakeList(const char**, std::va_list*, char, Py_ssize_t, int);
61static PyObject* doMakeDict(const char**, std::va_list*, char, Py_ssize_t, int);
62
63static void doIgnore(const char** p_format, std::va_list* p_va, char endchar,
64 Py_ssize_t n, int flags) {
65 DCHECK(PyErr_Occurred() != nullptr, "exception has not been raised");
66 PyObject* v = PyTuple_New(n);
67 for (Py_ssize_t i = 0; i < n; i++) {
68 PyObject *exception, *value, *tb;
69 PyErr_Fetch(&exception, &value, &tb);
70 PyObject* w = makeValueFromFormat(p_format, p_va, flags);
71 PyErr_Restore(exception, value, tb);
72 if (w != nullptr) {
73 if (v != nullptr) {
74 PyTuple_SET_ITEM(v, i, w);
75 } else {
76 Py_DECREF(w);
77 }
78 }
79 }
80 Py_XDECREF(v);
81 if (**p_format != endchar) {
82 Thread::current()->raiseWithFmt(LayoutId::kSystemError,
83 "Unmatched paren in format");
84 return;
85 }
86 if (endchar != '\0') {
87 ++*p_format;
88 }
89}
90
91static PyObject* doMakeDict(const char** p_format, std::va_list* p_va,
92 char endchar, Py_ssize_t n, int flags) {
93 if (n < 0) {
94 return nullptr;
95 }
96 if (n % 2) {
97 Thread::current()->raiseWithFmt(LayoutId::kSystemError, "Bad dict format");
98 doIgnore(p_format, p_va, endchar, n, flags);
99 return nullptr;
100 }
101 // Note that we can't bail immediately on error as this will leak refcounts on
102 // any 'N' arguments.
103 PyObject* d = PyDict_New();
104 if (d == nullptr) {
105 doIgnore(p_format, p_va, endchar, n, flags);
106 return nullptr;
107 }
108 for (Py_ssize_t i = 0; i < n; i += 2) {
109 PyObject* k = makeValueFromFormat(p_format, p_va, flags);
110 if (k == nullptr) {
111 doIgnore(p_format, p_va, endchar, n - i - 1, flags);
112 Py_DECREF(d);
113 return nullptr;
114 }
115 PyObject* v = makeValueFromFormat(p_format, p_va, flags);
116 if (v == nullptr || PyDict_SetItem(d, k, v) < 0) {
117 doIgnore(p_format, p_va, endchar, n - i - 2, flags);
118 Py_DECREF(k);
119 Py_XDECREF(v);
120 Py_DECREF(d);
121 return nullptr;
122 }
123 Py_DECREF(k);
124 Py_DECREF(v);
125 }
126 if (**p_format != endchar) {
127 Py_DECREF(d);
128 Thread::current()->raiseWithFmt(LayoutId::kSystemError,
129 "Unmatched paren in format");
130 return nullptr;
131 }
132 if (endchar != '\0') {
133 ++*p_format;
134 }
135 return d;
136}
137
138static PyObject* doMakeList(const char** p_format, std::va_list* p_va,
139 char endchar, Py_ssize_t n, int flags) {
140 if (n < 0) {
141 return nullptr;
142 }
143 // Note that we can't bail immediately on error as this will leak refcounts on
144 // any 'N' arguments.
145 PyObject* v = PyList_New(n);
146 if (v == nullptr) {
147 doIgnore(p_format, p_va, endchar, n, flags);
148 return nullptr;
149 }
150 for (Py_ssize_t i = 0; i < n; i++) {
151 PyObject* w = makeValueFromFormat(p_format, p_va, flags);
152 if (w == nullptr) {
153 doIgnore(p_format, p_va, endchar, n - i - 1, flags);
154 Py_DECREF(v);
155 return nullptr;
156 }
157 PyList_SetItem(v, i, w);
158 }
159 if (**p_format != endchar) {
160 Py_DECREF(v);
161 Thread::current()->raiseWithFmt(LayoutId::kSystemError,
162 "Unmatched paren in format");
163 return nullptr;
164 }
165 if (endchar != '\0') {
166 ++*p_format;
167 }
168 return v;
169}
170
171static PyObject* doMakeTuple(const char** p_format, std::va_list* p_va,
172 char endchar, Py_ssize_t n, int flags) {
173 if (n < 0) {
174 return nullptr;
175 }
176 // Note that we can't bail immediately on error as this will leak refcounts on
177 // any 'N' arguments.
178 PyObject* v = PyTuple_New(n);
179 if (v == nullptr) {
180 doIgnore(p_format, p_va, endchar, n, flags);
181 return nullptr;
182 }
183 for (Py_ssize_t i = 0; i < n; i++) {
184 PyObject* w = makeValueFromFormat(p_format, p_va, flags);
185 if (w == nullptr) {
186 doIgnore(p_format, p_va, endchar, n - i - 1, flags);
187 Py_DECREF(v);
188 return nullptr;
189 }
190 PyTuple_SET_ITEM(v, i, w);
191 }
192 if (**p_format != endchar) {
193 Py_DECREF(v);
194 Thread::current()->raiseWithFmt(LayoutId::kSystemError,
195 "Unmatched paren in format");
196 return nullptr;
197 }
198 if (endchar != '\0') {
199 ++*p_format;
200 }
201 return v;
202}
203
204Py_ssize_t countFormat(const char* format, char endchar) {
205 Py_ssize_t count = 0;
206 int level = 0;
207 while (level > 0 || *format != endchar) {
208 switch (*format) {
209 case '\0':
210 // Premature end
211 Thread::current()->raiseWithFmt(LayoutId::kSystemError,
212 "unmatched paren in format");
213 return -1;
214 case '(':
215 case '[':
216 case '{':
217 if (level == 0) {
218 count++;
219 }
220 level++;
221 break;
222 case ')':
223 case ']':
224 case '}':
225 level--;
226 break;
227 case '#':
228 case '&':
229 case ',':
230 case ':':
231 case ' ':
232 case '\t':
233 break;
234 default:
235 if (level == 0) {
236 count++;
237 }
238 }
239 format++;
240 }
241 return count;
242}
243
244PyObject* makeValueFromFormat(const char** p_format, std::va_list* p_va,
245 int flags) {
246 for (;;) {
247 switch (*(*p_format)++) {
248 case '(':
249 return doMakeTuple(p_format, p_va, ')', countFormat(*p_format, ')'),
250 flags);
251
252 case '[':
253 return doMakeList(p_format, p_va, ']', countFormat(*p_format, ']'),
254 flags);
255
256 case '{':
257 return doMakeDict(p_format, p_va, '}', countFormat(*p_format, '}'),
258 flags);
259
260 case 'b':
261 case 'B':
262 case 'h':
263 case 'i':
264 return PyLong_FromLong(va_arg(*p_va, int));
265
266 case 'H':
267 return PyLong_FromLong(va_arg(*p_va, unsigned int));
268
269 case 'I':
270 return PyLong_FromUnsignedLong(va_arg(*p_va, unsigned int));
271
272 case 'n':
273 if (sizeof(size_t) != sizeof(long)) {
274 return PyLong_FromSsize_t(va_arg(*p_va, Py_ssize_t));
275 }
276 FALLTHROUGH;
277 case 'l':
278 return PyLong_FromLong(va_arg(*p_va, long));
279
280 case 'k': {
281 return PyLong_FromUnsignedLong(va_arg(*p_va, unsigned long));
282 }
283
284 case 'L':
285 return PyLong_FromLongLong(va_arg(*p_va, long long));
286
287 case 'K':
288 return PyLong_FromUnsignedLongLong(va_arg(*p_va, unsigned long long));
289
290 case 'u': {
291 Py_UNICODE* u = va_arg(*p_va, Py_UNICODE*);
292 Py_ssize_t n;
293 if (**p_format == '#') {
294 ++*p_format;
295 if (flags & kFlagSizeT) {
296 n = va_arg(*p_va, Py_ssize_t);
297 } else {
298 n = va_arg(*p_va, int);
299 }
300 } else {
301 n = -1;
302 }
303 PyObject* v;
304 if (u == nullptr) {
305 v = Py_None;
306 Py_INCREF(v);
307 } else {
308 if (n < 0) {
309 n = std::wcslen(u);
310 }
311 v = PyUnicode_FromWideChar(u, n);
312 }
313 return v;
314 }
315 case 'f':
316 case 'd':
317 return PyFloat_FromDouble(va_arg(*p_va, double));
318
319 case 'D':
320 return PyComplex_FromCComplex(*va_arg(*p_va, Py_complex*));
321
322 case 'c': {
323 char ch = va_arg(*p_va, int);
324 return PyBytes_FromStringAndSize(&ch, 1);
325 }
326 case 'C': {
327 int i = va_arg(*p_va, int);
328 return PyUnicode_FromOrdinal(i);
329 }
330
331 case 's':
332 case 'z':
333 case 'U': { // XXX deprecated alias
334 const char* str = va_arg(*p_va, const char*);
335 Py_ssize_t n;
336 if (**p_format == '#') {
337 ++*p_format;
338 if (flags & kFlagSizeT) {
339 n = va_arg(*p_va, Py_ssize_t);
340 } else {
341 n = va_arg(*p_va, int);
342 }
343 } else {
344 n = -1;
345 }
346 PyObject* v;
347 if (str == nullptr) {
348 v = Py_None;
349 Py_INCREF(v);
350 } else {
351 if (n < 0) {
352 size_t m = std::strlen(str);
353 if (m > kMaxWord) {
354 Thread::current()->raiseWithFmt(
355 LayoutId::kOverflowError,
356 "string too long for Python string");
357 return nullptr;
358 }
359 n = static_cast<Py_ssize_t>(m);
360 }
361 v = PyUnicode_FromStringAndSize(str, n);
362 }
363 return v;
364 }
365
366 case 'y': {
367 PyObject* v;
368 const char* str = va_arg(*p_va, const char*);
369 Py_ssize_t n;
370 if (**p_format == '#') {
371 ++*p_format;
372 if (flags & kFlagSizeT) {
373 n = va_arg(*p_va, Py_ssize_t);
374 } else {
375 n = va_arg(*p_va, int);
376 }
377 } else {
378 n = -1;
379 }
380 if (str == nullptr) {
381 v = Py_None;
382 Py_INCREF(v);
383 } else {
384 if (n < 0) {
385 size_t m = std::strlen(str);
386 if (m > kMaxWord) {
387 Thread::current()->raiseWithFmt(
388 LayoutId::kOverflowError, "string too long for Python bytes");
389 return nullptr;
390 }
391 n = static_cast<Py_ssize_t>(m);
392 }
393 v = PyBytes_FromStringAndSize(str, n);
394 }
395 return v;
396 }
397
398 case 'N':
399 case 'S':
400 case 'O':
401 if (**p_format == '&') {
402 typedef PyObject* (*converter)(void*);
403 converter func = va_arg(*p_va, converter);
404 void* arg = va_arg(*p_va, void*);
405 ++*p_format;
406 return (*func)(arg);
407 } else {
408 PyObject* v = va_arg(*p_va, PyObject*);
409 if (v != nullptr) {
410 if (*(*p_format - 1) != 'N') Py_INCREF(v);
411 } else if (!PyErr_Occurred()) {
412 // If a NULL was passed because a call that should have constructed
413 // a value failed, that's OK, and we pass the error on; but if no
414 // error occurred it's not clear that the caller knew what she was
415 // doing.
416 Thread::current()->raiseWithFmt(
417 LayoutId::kSystemError, "NULL object passed to Py_BuildValue");
418 }
419 return v;
420 }
421
422 case ':':
423 case ',':
424 case ' ':
425 case '\t':
426 break;
427
428 default:
429 Thread::current()->raiseWithFmt(
430 LayoutId::kSystemError, "bad format char passed to Py_BuildValue");
431 return nullptr;
432 }
433 }
434}
435
436static PyObject* vaBuildValue(const char* format, std::va_list va, int flags) {
437 Py_ssize_t n = countFormat(format, '\0');
438 if (n < 0) {
439 return nullptr;
440 }
441 if (n == 0) {
442 Py_INCREF(Py_None);
443 return Py_None;
444 }
445 std::va_list lva;
446 va_copy(lva, va);
447 const char* f = format;
448 PyObject* retval;
449 if (n == 1) {
450 retval = makeValueFromFormat(&f, &lva, flags);
451 } else {
452 retval = doMakeTuple(&f, &lva, '\0', n, flags);
453 }
454 va_end(lva);
455 return retval;
456}
457
458PY_EXPORT PyObject* Py_VaBuildValue(const char* format, std::va_list va) {
459 return vaBuildValue(format, va, 0);
460}
461
462PY_EXPORT PyObject* _Py_VaBuildValue_SizeT(const char* format,
463 std::va_list va) {
464 return vaBuildValue(format, va, kFlagSizeT);
465}
466
467PY_EXPORT PyObject* Py_BuildValue(const char* format, ...) {
468 std::va_list va;
469 va_start(va, format);
470 PyObject* retval = vaBuildValue(format, va, 0);
471 va_end(va);
472 return retval;
473}
474
475PY_EXPORT PyObject* _Py_BuildValue_SizeT(const char* format, ...) {
476 std::va_list va;
477 va_start(va, format);
478 PyObject* retval = vaBuildValue(format, va, kFlagSizeT);
479 va_end(va);
480 return retval;
481}
482
483} // namespace py