Coverage Report

Created: 2025-11-24 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/modsupport.c
Line
Count
Source
1
2
/* Module support implementation */
3
4
#include "Python.h"
5
#include "pycore_abstract.h"   // _PyIndex_Check()
6
#include "pycore_object.h"     // _PyType_IsReady()
7
#include "pycore_unicodeobject.h"     // _PyUnicodeWriter_FormatV()
8
9
typedef double va_double;
10
11
static PyObject *va_build_value(const char *, va_list);
12
13
14
int
15
_Py_convert_optional_to_ssize_t(PyObject *obj, void *result)
16
5.65M
{
17
5.65M
    Py_ssize_t limit;
18
5.65M
    if (obj == Py_None) {
19
0
        return 1;
20
0
    }
21
5.65M
    else if (_PyIndex_Check(obj)) {
22
5.65M
        limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
23
5.65M
        if (limit == -1 && PyErr_Occurred()) {
24
69
            return 0;
25
69
        }
26
5.65M
    }
27
0
    else {
28
0
        PyErr_Format(PyExc_TypeError,
29
0
                     "argument should be integer or None, not '%.200s'",
30
0
                     Py_TYPE(obj)->tp_name);
31
0
        return 0;
32
0
    }
33
5.65M
    *((Py_ssize_t *)result) = limit;
34
5.65M
    return 1;
35
5.65M
}
36
37
int
38
_Py_convert_optional_to_non_negative_ssize_t(PyObject *obj, void *result)
39
0
{
40
0
    if (!_Py_convert_optional_to_ssize_t(obj, result)) {
41
0
        return 0;
42
0
    }
43
0
    if (obj != Py_None && *((Py_ssize_t *)result) < 0) {
44
0
        PyErr_SetString(PyExc_ValueError, "argument cannot be negative");
45
0
        return 0;
46
0
    }
47
0
    return 1;
48
0
}
49
50
51
/* Helper for mkvalue() to scan the length of a format */
52
53
static Py_ssize_t
54
countformat(const char *format, char endchar)
55
7.34M
{
56
7.34M
    Py_ssize_t count = 0;
57
7.34M
    int level = 0;
58
31.1M
    while (level > 0 || *format != endchar) {
59
23.8M
        switch (*format) {
60
0
        case '\0':
61
            /* Premature end */
62
0
            PyErr_SetString(PyExc_SystemError,
63
0
                            "unmatched paren in format");
64
0
            return -1;
65
2.27M
        case '(':
66
2.27M
        case '[':
67
2.27M
        case '{':
68
2.27M
            if (level == 0) {
69
2.27M
                count++;
70
2.27M
            }
71
2.27M
            level++;
72
2.27M
            break;
73
2.27M
        case ')':
74
2.27M
        case ']':
75
2.27M
        case '}':
76
2.27M
            level--;
77
2.27M
            break;
78
956k
        case '#':
79
956k
        case '&':
80
956k
        case ',':
81
956k
        case ':':
82
956k
        case ' ':
83
956k
        case '\t':
84
956k
            break;
85
18.3M
        default:
86
18.3M
            if (level == 0) {
87
14.0M
                count++;
88
14.0M
            }
89
23.8M
        }
90
23.8M
        format++;
91
23.8M
    }
92
7.34M
    return count;
93
7.34M
}
94
95
96
/* Generic function to create a value -- the inverse of getargs() */
97
/* After an original idea and first implementation by Steven Miale */
98
99
static PyObject *do_mktuple(const char**, va_list *, char, Py_ssize_t);
100
static int do_mkstack(PyObject **, const char**, va_list *, char, Py_ssize_t);
101
static PyObject *do_mklist(const char**, va_list *, char, Py_ssize_t);
102
static PyObject *do_mkdict(const char**, va_list *, char, Py_ssize_t);
103
static PyObject *do_mkvalue(const char**, va_list *);
104
105
static int
106
check_end(const char **p_format, char endchar)
107
4.91M
{
108
4.91M
    const char *f = *p_format;
109
4.91M
    while (*f != endchar) {
110
0
        if (*f != ' ' && *f != '\t' && *f != ',' && *f != ':') {
111
0
            PyErr_SetString(PyExc_SystemError,
112
0
                            "Unmatched paren in format");
113
0
            return 0;
114
0
        }
115
0
        f++;
116
0
    }
117
4.91M
    if (endchar) {
118
2.27M
        f++;
119
2.27M
    }
120
4.91M
    *p_format = f;
121
4.91M
    return 1;
122
4.91M
}
123
124
static void
125
do_ignore(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n)
126
0
{
127
0
    assert(PyErr_Occurred());
128
0
    PyObject *v = PyTuple_New(n);
129
0
    for (Py_ssize_t i = 0; i < n; i++) {
130
0
        PyObject *exc = PyErr_GetRaisedException();
131
0
        PyObject *w = do_mkvalue(p_format, p_va);
132
0
        PyErr_SetRaisedException(exc);
133
0
        if (w != NULL) {
134
0
            if (v != NULL) {
135
0
                PyTuple_SET_ITEM(v, i, w);
136
0
            }
137
0
            else {
138
0
                Py_DECREF(w);
139
0
            }
140
0
        }
141
0
    }
142
0
    Py_XDECREF(v);
143
0
    if (!check_end(p_format, endchar)) {
144
0
        return;
145
0
    }
146
0
}
147
148
static PyObject *
149
do_mkdict(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n)
150
2.30k
{
151
2.30k
    PyObject *d;
152
2.30k
    Py_ssize_t i;
153
2.30k
    if (n < 0)
154
0
        return NULL;
155
2.30k
    if (n % 2) {
156
0
        PyErr_SetString(PyExc_SystemError,
157
0
                        "Bad dict format");
158
0
        do_ignore(p_format, p_va, endchar, n);
159
0
        return NULL;
160
0
    }
161
    /* Note that we can't bail immediately on error as this will leak
162
       refcounts on any 'N' arguments. */
163
2.30k
    if ((d = PyDict_New()) == NULL) {
164
0
        do_ignore(p_format, p_va, endchar, n);
165
0
        return NULL;
166
0
    }
167
11.3k
    for (i = 0; i < n; i+= 2) {
168
9.02k
        PyObject *k, *v;
169
170
9.02k
        k = do_mkvalue(p_format, p_va);
171
9.02k
        if (k == NULL) {
172
0
            do_ignore(p_format, p_va, endchar, n - i - 1);
173
0
            Py_DECREF(d);
174
0
            return NULL;
175
0
        }
176
9.02k
        v = do_mkvalue(p_format, p_va);
177
9.02k
        if (v == NULL || PyDict_SetItem(d, k, v) < 0) {
178
0
            do_ignore(p_format, p_va, endchar, n - i - 2);
179
0
            Py_DECREF(k);
180
0
            Py_XDECREF(v);
181
0
            Py_DECREF(d);
182
0
            return NULL;
183
0
        }
184
9.02k
        Py_DECREF(k);
185
9.02k
        Py_DECREF(v);
186
9.02k
    }
187
2.30k
    if (!check_end(p_format, endchar)) {
188
0
        Py_DECREF(d);
189
0
        return NULL;
190
0
    }
191
2.30k
    return d;
192
2.30k
}
193
194
static PyObject *
195
do_mklist(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n)
196
0
{
197
0
    PyObject *v;
198
0
    Py_ssize_t i;
199
0
    if (n < 0)
200
0
        return NULL;
201
    /* Note that we can't bail immediately on error as this will leak
202
       refcounts on any 'N' arguments. */
203
0
    v = PyList_New(n);
204
0
    if (v == NULL) {
205
0
        do_ignore(p_format, p_va, endchar, n);
206
0
        return NULL;
207
0
    }
208
0
    for (i = 0; i < n; i++) {
209
0
        PyObject *w = do_mkvalue(p_format, p_va);
210
0
        if (w == NULL) {
211
0
            do_ignore(p_format, p_va, endchar, n - i - 1);
212
0
            Py_DECREF(v);
213
0
            return NULL;
214
0
        }
215
0
        PyList_SET_ITEM(v, i, w);
216
0
    }
217
0
    if (!check_end(p_format, endchar)) {
218
0
        Py_DECREF(v);
219
0
        return NULL;
220
0
    }
221
0
    return v;
222
0
}
223
224
static int
225
do_mkstack(PyObject **stack, const char **p_format, va_list *p_va,
226
           char endchar, Py_ssize_t n)
227
1.46M
{
228
1.46M
    Py_ssize_t i;
229
230
1.46M
    if (n < 0) {
231
0
        return -1;
232
0
    }
233
    /* Note that we can't bail immediately on error as this will leak
234
       refcounts on any 'N' arguments. */
235
8.44M
    for (i = 0; i < n; i++) {
236
6.98M
        PyObject *w = do_mkvalue(p_format, p_va);
237
6.98M
        if (w == NULL) {
238
0
            do_ignore(p_format, p_va, endchar, n - i - 1);
239
0
            goto error;
240
0
        }
241
6.98M
        stack[i] = w;
242
6.98M
    }
243
1.46M
    if (!check_end(p_format, endchar)) {
244
0
        goto error;
245
0
    }
246
1.46M
    return 0;
247
248
0
error:
249
0
    n = i;
250
0
    for (i=0; i < n; i++) {
251
0
        Py_DECREF(stack[i]);
252
0
    }
253
0
    return -1;
254
1.46M
}
255
256
static PyObject *
257
do_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n)
258
3.44M
{
259
3.44M
    PyObject *v;
260
3.44M
    Py_ssize_t i;
261
3.44M
    if (n < 0)
262
0
        return NULL;
263
    /* Note that we can't bail immediately on error as this will leak
264
       refcounts on any 'N' arguments. */
265
3.44M
    if ((v = PyTuple_New(n)) == NULL) {
266
0
        do_ignore(p_format, p_va, endchar, n);
267
0
        return NULL;
268
0
    }
269
10.3M
    for (i = 0; i < n; i++) {
270
6.87M
        PyObject *w = do_mkvalue(p_format, p_va);
271
6.87M
        if (w == NULL) {
272
0
            do_ignore(p_format, p_va, endchar, n - i - 1);
273
0
            Py_DECREF(v);
274
0
            return NULL;
275
0
        }
276
6.87M
        PyTuple_SET_ITEM(v, i, w);
277
6.87M
    }
278
3.44M
    if (!check_end(p_format, endchar)) {
279
0
        Py_DECREF(v);
280
0
        return NULL;
281
0
    }
282
3.44M
    return v;
283
3.44M
}
284
285
static PyObject *
286
do_mkvalue(const char **p_format, va_list *p_va)
287
16.3M
{
288
16.3M
    for (;;) {
289
16.3M
        switch (*(*p_format)++) {
290
2.26M
        case '(':
291
2.26M
            return do_mktuple(p_format, p_va, ')',
292
2.26M
                              countformat(*p_format, ')'));
293
294
0
        case '[':
295
0
            return do_mklist(p_format, p_va, ']',
296
0
                             countformat(*p_format, ']'));
297
298
2.30k
        case '{':
299
2.30k
            return do_mkdict(p_format, p_va, '}',
300
2.30k
                             countformat(*p_format, '}'));
301
302
0
        case 'b':
303
0
        case 'B':
304
0
        case 'h':
305
1.16M
        case 'i':
306
1.16M
            return PyLong_FromLong((long)va_arg(*p_va, int));
307
308
0
        case 'H':
309
0
            return PyLong_FromLong((long)va_arg(*p_va, unsigned int));
310
311
40
        case 'I':
312
40
        {
313
40
            unsigned int n;
314
40
            n = va_arg(*p_va, unsigned int);
315
40
            return PyLong_FromUnsignedLong(n);
316
0
        }
317
318
3.40M
        case 'n':
319
#if SIZEOF_SIZE_T!=SIZEOF_LONG
320
            return PyLong_FromSsize_t(va_arg(*p_va, Py_ssize_t));
321
#endif
322
            /* Fall through from 'n' to 'l' if Py_ssize_t is long */
323
3.40M
            _Py_FALLTHROUGH;
324
3.40M
        case 'l':
325
3.40M
            return PyLong_FromLong(va_arg(*p_va, long));
326
327
0
        case 'k':
328
0
        {
329
0
            unsigned long n;
330
0
            n = va_arg(*p_va, unsigned long);
331
0
            return PyLong_FromUnsignedLong(n);
332
3.40M
        }
333
334
0
        case 'L':
335
0
            return PyLong_FromLongLong((long long)va_arg(*p_va, long long));
336
337
0
        case 'K':
338
0
            return PyLong_FromUnsignedLongLong(
339
0
                va_arg(*p_va, unsigned long long));
340
341
0
        case 'u':
342
0
        {
343
0
            PyObject *v;
344
0
            const wchar_t *u = va_arg(*p_va, wchar_t*);
345
0
            Py_ssize_t n;
346
0
            if (**p_format == '#') {
347
0
                ++*p_format;
348
0
                n = va_arg(*p_va, Py_ssize_t);
349
0
            }
350
0
            else
351
0
                n = -1;
352
0
            if (u == NULL) {
353
0
                v = Py_NewRef(Py_None);
354
0
            }
355
0
            else {
356
0
                if (n < 0)
357
0
                    n = wcslen(u);
358
0
                v = PyUnicode_FromWideChar(u, n);
359
0
            }
360
0
            return v;
361
3.40M
        }
362
0
        case 'f':
363
0
        case 'd':
364
0
            return PyFloat_FromDouble(
365
0
                (double)va_arg(*p_va, va_double));
366
367
0
        case 'D':
368
0
            return PyComplex_FromCComplex(
369
0
                *((Py_complex *)va_arg(*p_va, Py_complex *)));
370
371
248
        case 'c':
372
248
        {
373
248
            char p[1];
374
248
            p[0] = (char)va_arg(*p_va, int);
375
248
            return PyBytes_FromStringAndSize(p, 1);
376
0
        }
377
0
        case 'C':
378
0
        {
379
0
            int i = va_arg(*p_va, int);
380
0
            return PyUnicode_FromOrdinal(i);
381
0
        }
382
0
        case 'p':
383
0
        {
384
0
            int i = va_arg(*p_va, int);
385
0
            return PyBool_FromLong(i);
386
0
        }
387
388
2.39M
        case 's':
389
2.40M
        case 'z':
390
2.40M
        case 'U':   /* XXX deprecated alias */
391
2.40M
        {
392
2.40M
            PyObject *v;
393
2.40M
            const char *str = va_arg(*p_va, const char *);
394
2.40M
            Py_ssize_t n;
395
2.40M
            if (**p_format == '#') {
396
0
                ++*p_format;
397
0
                n = va_arg(*p_va, Py_ssize_t);
398
0
            }
399
2.40M
            else
400
2.40M
                n = -1;
401
2.40M
            if (str == NULL) {
402
0
                v = Py_NewRef(Py_None);
403
0
            }
404
2.40M
            else {
405
2.40M
                if (n < 0) {
406
2.40M
                    size_t m = strlen(str);
407
2.40M
                    if (m > PY_SSIZE_T_MAX) {
408
0
                        PyErr_SetString(PyExc_OverflowError,
409
0
                            "string too long for Python string");
410
0
                        return NULL;
411
0
                    }
412
2.40M
                    n = (Py_ssize_t)m;
413
2.40M
                }
414
2.40M
                v = PyUnicode_FromStringAndSize(str, n);
415
2.40M
            }
416
2.40M
            return v;
417
2.40M
        }
418
419
956k
        case 'y':
420
956k
        {
421
956k
            PyObject *v;
422
956k
            const char *str = va_arg(*p_va, const char *);
423
956k
            Py_ssize_t n;
424
956k
            if (**p_format == '#') {
425
956k
                ++*p_format;
426
956k
                n = va_arg(*p_va, Py_ssize_t);
427
956k
            }
428
1
            else
429
1
                n = -1;
430
956k
            if (str == NULL) {
431
0
                v = Py_NewRef(Py_None);
432
0
            }
433
956k
            else {
434
956k
                if (n < 0) {
435
1
                    size_t m = strlen(str);
436
1
                    if (m > PY_SSIZE_T_MAX) {
437
0
                        PyErr_SetString(PyExc_OverflowError,
438
0
                            "string too long for Python bytes");
439
0
                        return NULL;
440
0
                    }
441
1
                    n = (Py_ssize_t)m;
442
1
                }
443
956k
                v = PyBytes_FromStringAndSize(str, n);
444
956k
            }
445
956k
            return v;
446
956k
        }
447
448
3.88M
        case 'N':
449
3.88M
        case 'S':
450
6.11M
        case 'O':
451
6.11M
        if (**p_format == '&') {
452
0
            typedef PyObject *(*converter)(void *);
453
0
            converter func = va_arg(*p_va, converter);
454
0
            void *arg = va_arg(*p_va, void *);
455
0
            ++*p_format;
456
0
            return (*func)(arg);
457
0
        }
458
6.11M
        else {
459
6.11M
            PyObject *v;
460
6.11M
            v = va_arg(*p_va, PyObject *);
461
6.11M
            if (v != NULL) {
462
6.11M
                if (*(*p_format - 1) != 'N')
463
2.23M
                    Py_INCREF(v);
464
6.11M
            }
465
0
            else if (!PyErr_Occurred())
466
                /* If a NULL was passed
467
                 * because a call that should
468
                 * have constructed a value
469
                 * failed, that's OK, and we
470
                 * pass the error on; but if
471
                 * no error occurred it's not
472
                 * clear that the caller knew
473
                 * what she was doing. */
474
0
                PyErr_SetString(PyExc_SystemError,
475
0
                    "NULL object passed to Py_BuildValue");
476
6.11M
            return v;
477
6.11M
        }
478
479
0
        case ':':
480
0
        case ',':
481
0
        case ' ':
482
0
        case '\t':
483
0
            break;
484
485
0
        default:
486
0
            PyErr_SetString(PyExc_SystemError,
487
0
                "bad format char passed to Py_BuildValue");
488
0
            return NULL;
489
490
16.3M
        }
491
16.3M
    }
492
16.3M
}
493
494
495
PyObject *
496
Py_BuildValue(const char *format, ...)
497
3.02M
{
498
3.02M
    va_list va;
499
3.02M
    PyObject* retval;
500
3.02M
    va_start(va, format);
501
3.02M
    retval = va_build_value(format, va);
502
3.02M
    va_end(va);
503
3.02M
    return retval;
504
3.02M
}
505
506
PyAPI_FUNC(PyObject *) /* abi only */
507
_Py_BuildValue_SizeT(const char *format, ...)
508
0
{
509
0
    va_list va;
510
0
    PyObject* retval;
511
0
    va_start(va, format);
512
0
    retval = va_build_value(format, va);
513
0
    va_end(va);
514
0
    return retval;
515
0
}
516
517
PyObject *
518
Py_VaBuildValue(const char *format, va_list va)
519
595k
{
520
595k
    return va_build_value(format, va);
521
595k
}
522
523
PyAPI_FUNC(PyObject *) /* abi only */
524
_Py_VaBuildValue_SizeT(const char *format, va_list va)
525
0
{
526
0
    return va_build_value(format, va);
527
0
}
528
529
static PyObject *
530
va_build_value(const char *format, va_list va)
531
3.61M
{
532
3.61M
    const char *f = format;
533
3.61M
    Py_ssize_t n = countformat(f, '\0');
534
3.61M
    va_list lva;
535
3.61M
    PyObject *retval;
536
537
3.61M
    if (n < 0)
538
0
        return NULL;
539
3.61M
    if (n == 0) {
540
0
        Py_RETURN_NONE;
541
0
    }
542
3.61M
    va_copy(lva, va);
543
3.61M
    if (n == 1) {
544
2.43M
        retval = do_mkvalue(&f, &lva);
545
2.43M
    } else {
546
1.18M
        retval = do_mktuple(&f, &lva, '\0', n);
547
1.18M
    }
548
3.61M
    va_end(lva);
549
3.61M
    return retval;
550
3.61M
}
551
552
PyObject **
553
_Py_VaBuildStack(PyObject **small_stack, Py_ssize_t small_stack_len,
554
                const char *format, va_list va, Py_ssize_t *p_nargs)
555
1.46M
{
556
1.46M
    const char *f;
557
1.46M
    Py_ssize_t n;
558
1.46M
    va_list lva;
559
1.46M
    PyObject **stack;
560
1.46M
    int res;
561
562
1.46M
    n = countformat(format, '\0');
563
1.46M
    if (n < 0) {
564
0
        *p_nargs = 0;
565
0
        return NULL;
566
0
    }
567
568
1.46M
    if (n == 0) {
569
0
        *p_nargs = 0;
570
0
        return small_stack;
571
0
    }
572
573
1.46M
    if (n <= small_stack_len) {
574
1.46M
        stack = small_stack;
575
1.46M
    }
576
168
    else {
577
168
        stack = PyMem_Malloc(n * sizeof(stack[0]));
578
168
        if (stack == NULL) {
579
0
            PyErr_NoMemory();
580
0
            return NULL;
581
0
        }
582
168
    }
583
584
1.46M
    va_copy(lva, va);
585
1.46M
    f = format;
586
1.46M
    res = do_mkstack(stack, &f, &lva, '\0', n);
587
1.46M
    va_end(lva);
588
589
1.46M
    if (res < 0) {
590
0
        if (stack != small_stack) {
591
0
            PyMem_Free(stack);
592
0
        }
593
0
        return NULL;
594
0
    }
595
596
1.46M
    *p_nargs = n;
597
1.46M
    return stack;
598
1.46M
}
599
600
601
int
602
PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value)
603
14.8k
{
604
14.8k
    if (!PyModule_Check(mod)) {
605
0
        PyErr_SetString(PyExc_TypeError,
606
0
                        "PyModule_AddObjectRef() first argument "
607
0
                        "must be a module");
608
0
        return -1;
609
0
    }
610
14.8k
    if (!value) {
611
0
        if (!PyErr_Occurred()) {
612
0
            PyErr_SetString(PyExc_SystemError,
613
0
                            "PyModule_AddObjectRef() must be called "
614
0
                            "with an exception raised if value is NULL");
615
0
        }
616
0
        return -1;
617
0
    }
618
619
14.8k
    PyObject *dict = PyModule_GetDict(mod);
620
14.8k
    if (dict == NULL) {
621
        /* Internal error -- modules must have a dict! */
622
0
        PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
623
0
                     PyModule_GetName(mod));
624
0
        return -1;
625
0
    }
626
14.8k
    return PyDict_SetItemString(dict, name, value);
627
14.8k
}
628
629
int
630
PyModule_Add(PyObject *mod, const char *name, PyObject *value)
631
11.2k
{
632
11.2k
    int res = PyModule_AddObjectRef(mod, name, value);
633
11.2k
    Py_XDECREF(value);
634
11.2k
    return res;
635
11.2k
}
636
637
int
638
PyModule_AddObject(PyObject *mod, const char *name, PyObject *value)
639
0
{
640
0
    int res = PyModule_AddObjectRef(mod, name, value);
641
0
    if (res == 0) {
642
0
        Py_DECREF(value);
643
0
    }
644
0
    return res;
645
0
}
646
647
int
648
PyModule_AddIntConstant(PyObject *m, const char *name, long value)
649
10.4k
{
650
10.4k
    return PyModule_Add(m, name, PyLong_FromLong(value));
651
10.4k
}
652
653
int
654
PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
655
155
{
656
155
    return PyModule_Add(m, name, PyUnicode_FromString(value));
657
155
}
658
659
int
660
PyModule_AddType(PyObject *module, PyTypeObject *type)
661
1.51k
{
662
1.51k
    if (!_PyType_IsReady(type) && PyType_Ready(type) < 0) {
663
0
        return -1;
664
0
    }
665
666
1.51k
    const char *name = _PyType_Name(type);
667
1.51k
    assert(name != NULL);
668
669
1.51k
    return PyModule_AddObjectRef(module, name, (PyObject *)type);
670
1.51k
}
671
672
static int _abiinfo_raise(const char *module_name, const char *format, ...)
673
0
{
674
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
675
0
    if (!writer) {
676
0
        return -1;
677
0
    }
678
0
    if (module_name) {
679
0
        if (PyUnicodeWriter_WriteUTF8(writer, module_name, -1) < 0) {
680
0
            PyUnicodeWriter_Discard(writer);
681
0
            return -1;
682
0
        }
683
0
        if (PyUnicodeWriter_WriteASCII(writer, ": ", 2) < 0) {
684
0
            PyUnicodeWriter_Discard(writer);
685
0
            return -1;
686
0
        }
687
0
    }
688
0
    va_list vargs;
689
0
    va_start(vargs, format);
690
0
    if (_PyUnicodeWriter_FormatV(writer, format, vargs) < 0) {
691
0
        PyUnicodeWriter_Discard(writer);
692
0
        return -1;
693
0
    }
694
0
    PyObject *message = PyUnicodeWriter_Finish(writer);
695
0
    if (!message) {
696
0
        return -1;
697
0
    }
698
0
    PyErr_SetObject(PyExc_ImportError, message);
699
0
    Py_DECREF(message);
700
0
    return -1;
701
0
}
702
703
int PyABIInfo_Check(PyABIInfo *info, const char *module_name)
704
10
{
705
10
    if (!info) {
706
0
        return _abiinfo_raise(module_name, "NULL PyABIInfo");
707
0
    }
708
709
    /* abiinfo_major_version */
710
10
    if (info->abiinfo_major_version == 0) {
711
0
        return 0;
712
0
    }
713
10
    if (info->abiinfo_major_version > 1) {
714
0
        return _abiinfo_raise(module_name, "PyABIInfo version too high");
715
0
    }
716
717
    /* Internal ABI */
718
10
    if (info->flags & PyABIInfo_INTERNAL) {
719
10
        if (info->abi_version && (info->abi_version != PY_VERSION_HEX)) {
720
0
            return _abiinfo_raise(
721
0
                module_name,
722
0
                "incompatible internal ABI (0x%x != 0x%x)",
723
0
                info->abi_version, PY_VERSION_HEX);
724
0
        }
725
10
    }
726
727
20
#define XY_MASK 0xffff0000
728
10
    if (info->flags & PyABIInfo_STABLE) {
729
        /* Greater-than major.minor version check */
730
0
        if (info->abi_version) {
731
0
            if ((info->abi_version & XY_MASK) > (PY_VERSION_HEX & XY_MASK)) {
732
0
                return _abiinfo_raise(
733
0
                    module_name,
734
0
                    "incompatible future stable ABI version (%d.%d)",
735
0
                    ((info->abi_version) >> 24) % 0xff,
736
0
                    ((info->abi_version) >> 16) % 0xff);
737
0
            }
738
0
            if (info->abi_version < Py_PACK_VERSION(3, 2)) {
739
0
                return _abiinfo_raise(
740
0
                    module_name,
741
0
                    "invalid stable ABI version (%d.%d)",
742
0
                    ((info->abi_version) >> 24) % 0xff,
743
0
                    ((info->abi_version) >> 16) % 0xff);
744
0
            }
745
0
        }
746
0
        if (info->flags & PyABIInfo_INTERNAL) {
747
0
            return _abiinfo_raise(module_name,
748
0
                                  "cannot use both internal and stable ABI");
749
0
        }
750
0
    }
751
10
    else {
752
        /* Exact major.minor version check */
753
10
        if (info->abi_version) {
754
10
            if ((info->abi_version & XY_MASK) != (PY_VERSION_HEX & XY_MASK)) {
755
0
                return _abiinfo_raise(
756
0
                    module_name,
757
0
                    "incompatible ABI version (%d.%d)",
758
0
                    ((info->abi_version) >> 24) % 0xff,
759
0
                    ((info->abi_version) >> 16) % 0xff);
760
0
            }
761
10
        }
762
10
    }
763
10
#undef XY_MASK
764
765
    /* Free-threading/GIL */
766
10
    uint16_t gilflags = info->flags & (PyABIInfo_GIL | PyABIInfo_FREETHREADED);
767
#if Py_GIL_DISABLED
768
    if (gilflags == PyABIInfo_GIL) {
769
        return _abiinfo_raise(module_name,
770
                              "incompatible with free-threaded CPython");
771
    }
772
#else
773
10
    if (gilflags == PyABIInfo_FREETHREADED) {
774
0
        return _abiinfo_raise(module_name,
775
0
                              "only compatible with free-threaded CPython");
776
0
    }
777
10
#endif
778
779
10
    return 0;
780
10
}
781
782
783
/* Exported functions for version helper macros */
784
785
#undef Py_PACK_FULL_VERSION
786
uint32_t
787
Py_PACK_FULL_VERSION(int x, int y, int z, int level, int serial)
788
0
{
789
0
    return _Py_PACK_FULL_VERSION(x, y, z, level, serial);
790
0
}
791
792
#undef Py_PACK_VERSION
793
uint32_t
794
Py_PACK_VERSION(int x, int y)
795
0
{
796
0
    return _Py_PACK_VERSION(x, y);
797
0
}