Coverage Report

Created: 2026-10-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/unicode_format.c
Line
Count
Source
1
/*
2
3
Unicode implementation based on original code by Fredrik Lundh,
4
modified by Marc-Andre Lemburg <mal@lemburg.com>.
5
6
Major speed upgrades to the method implementations at the Reykjavik
7
NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke.
8
9
Copyright (c) Corporation for National Research Initiatives.
10
11
--------------------------------------------------------------------
12
The original string type implementation is:
13
14
  Copyright (c) 1999 by Secret Labs AB
15
  Copyright (c) 1999 by Fredrik Lundh
16
17
By obtaining, using, and/or copying this software and/or its
18
associated documentation, you agree that you have read, understood,
19
and will comply with the following terms and conditions:
20
21
Permission to use, copy, modify, and distribute this software and its
22
associated documentation for any purpose and without fee is hereby
23
granted, provided that the above copyright notice appears in all
24
copies, and that both that copyright notice and this permission notice
25
appear in supporting documentation, and that the name of Secret Labs
26
AB or the author not be used in advertising or publicity pertaining to
27
distribution of the software without specific, written prior
28
permission.
29
30
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO
31
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
32
FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR
33
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
36
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37
--------------------------------------------------------------------
38
39
*/
40
41
// PyUnicode_Format() implementation
42
43
#include "Python.h"
44
#include "pycore_abstract.h"      // _PyIndex_Check()
45
#include "pycore_format.h"        // F_ALT
46
#include "pycore_long.h"          // _PyLong_FormatWriter()
47
#include "pycore_object.h"        // _PyObject_IsUniquelyReferenced()
48
#include "pycore_unicodeobject.h" // _Py_MAX_UNICODE
49
50
51
0
#define MAX_UNICODE _Py_MAX_UNICODE
52
12.3M
#define ensure_unicode _PyUnicode_EnsureUnicode
53
54
struct unicode_formatter_t {
55
    PyObject *args;
56
    int args_owned;
57
    Py_ssize_t arglen, argidx;
58
    PyObject *dict;
59
60
    int fmtkind;
61
    Py_ssize_t fmtcnt, fmtpos;
62
    const void *fmtdata;
63
    PyObject *fmtstr;
64
65
    _PyUnicodeWriter writer;
66
};
67
68
69
struct unicode_format_arg_t {
70
    Py_UCS4 ch;
71
    int flags;
72
    Py_ssize_t width;
73
    int prec;
74
    int sign;
75
    Py_ssize_t fmtstart;
76
    PyObject *key;
77
};
78
79
80
// Use FORMAT_ERROR("...%s", "") when there is no arguments.
81
850k
#define FORMAT_ERROR(EXC, FMT, ...) do {                                    \
82
850k
    if (arg->key != NULL) {                                                 \
83
0
        PyErr_Format((EXC), "format argument %R: " FMT,                     \
84
0
                     arg->key, __VA_ARGS__);                                \
85
0
    }                                                                       \
86
850k
    else if (ctx->argidx >= 0) {                                            \
87
0
        PyErr_Format((EXC), "format argument %zd: " FMT,                    \
88
0
                     ctx->argidx, __VA_ARGS__);                             \
89
0
    }                                                                       \
90
850k
    else {                                                                  \
91
850k
        PyErr_Format((EXC), "format argument: " FMT, __VA_ARGS__);          \
92
850k
    }                                                                       \
93
850k
} while (0)
94
95
96
static PyObject *
97
unicode_format_getnextarg(struct unicode_formatter_t *ctx, int allowone)
98
21.1M
{
99
21.1M
    Py_ssize_t argidx = ctx->argidx;
100
101
21.1M
    if (argidx < ctx->arglen && (allowone || ctx->arglen >= 0)) {
102
21.1M
        ctx->argidx++;
103
21.1M
        if (ctx->arglen >= 0) {
104
14.4M
            return PyTuple_GetItem(ctx->args, argidx);
105
14.4M
        }
106
6.71M
        else if (allowone) {
107
6.71M
            return ctx->args;
108
6.71M
        }
109
21.1M
    }
110
0
    PyErr_Format(PyExc_TypeError,
111
0
                 "not enough arguments for format string (got %zd)",
112
0
                 ctx->arglen < 0 ? 1 : ctx->arglen);
113
0
    return NULL;
114
21.1M
}
115
116
117
/* Returns a new reference to a PyUnicode object, or NULL on failure. */
118
119
/* Format a float into the writer if the writer is not NULL, or into *p_output
120
   otherwise.
121
122
   Return 0 on success, raise an exception and return -1 on error. */
123
static int
124
formatfloat(PyObject *v,
125
            struct unicode_formatter_t *ctx,
126
            struct unicode_format_arg_t *arg,
127
            PyObject **p_output,
128
            _PyUnicodeWriter *writer)
129
93
{
130
93
    char *p;
131
93
    double x;
132
93
    Py_ssize_t len;
133
93
    int prec;
134
93
    int dtoa_flags = 0;
135
136
93
    x = PyFloat_AsDouble(v);
137
93
    if (x == -1.0 && PyErr_Occurred()) {
138
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
139
0
            FORMAT_ERROR(PyExc_TypeError,
140
0
                         "%%%c requires a real number, not %T",
141
0
                         arg->ch, v);
142
0
        }
143
0
        return -1;
144
0
    }
145
146
93
    prec = arg->prec;
147
93
    if (prec < 0)
148
0
        prec = 6;
149
150
93
    if (arg->flags & F_ALT)
151
0
        dtoa_flags |= Py_DTSF_ALT;
152
93
    p = PyOS_double_to_string(x, arg->ch, prec, dtoa_flags, NULL);
153
93
    if (p == NULL)
154
0
        return -1;
155
93
    len = strlen(p);
156
93
    if (writer) {
157
0
        if (_PyUnicodeWriter_WriteASCIIString(writer, p, len) < 0) {
158
0
            PyMem_Free(p);
159
0
            return -1;
160
0
        }
161
0
    }
162
93
    else {
163
93
        *p_output = _PyUnicode_FromASCII(p, len);
164
93
        if (*p_output == NULL) {
165
0
            PyMem_Free(p);
166
0
            return -1;
167
0
        }
168
93
    }
169
93
    PyMem_Free(p);
170
93
    return 0;
171
93
}
172
173
174
/* formatlong() emulates the format codes d, u, o, x and X, and
175
 * the F_ALT flag, for Python's long (unbounded) ints.  It's not used for
176
 * Python's regular ints.
177
 * Return value:  a new PyUnicodeObject*, or NULL if error.
178
 *     The output string is of the form
179
 *         "-"? ("0x" | "0X")? digit+
180
 *     "0x"/"0X" are present only for x and X conversions, with F_ALT
181
 *         set in flags.  The case of hex digits will be correct,
182
 *     There will be at least prec digits, zero-filled on the left if
183
 *         necessary to get that many.
184
 * val          object to be converted
185
 * flags        bitmask of format flags; only F_ALT is looked at
186
 * prec         minimum number of digits; 0-fill on left if needed
187
 * type         a character in [duoxX]; u acts the same as d
188
 *
189
 * CAUTION:  o, x and X conversions on regular ints can never
190
 * produce a '-' sign, but can for Python's unbounded ints.
191
 */
192
PyObject *
193
_PyUnicode_FormatLong(PyObject *val, int alt, int prec, int type)
194
4.68M
{
195
4.68M
    PyObject *result = NULL;
196
4.68M
    char *buf;
197
4.68M
    Py_ssize_t i;
198
4.68M
    int sign;           /* 1 if '-', else 0 */
199
4.68M
    int len;            /* number of characters */
200
4.68M
    Py_ssize_t llen;
201
4.68M
    int numdigits;      /* len == numnondigits + numdigits */
202
4.68M
    int numnondigits = 0;
203
204
    /* Avoid exceeding SSIZE_T_MAX */
205
4.68M
    if (prec > INT_MAX-3) {
206
0
        PyErr_SetString(PyExc_OverflowError,
207
0
                        "precision too large");
208
0
        return NULL;
209
0
    }
210
211
4.68M
    assert(PyLong_Check(val));
212
213
4.68M
    switch (type) {
214
0
    default:
215
0
        Py_UNREACHABLE();
216
24
    case 'd':
217
24
    case 'i':
218
24
    case 'u':
219
        /* int and int subclasses should print numerically when a numeric */
220
        /* format code is used (see issue18780) */
221
24
        result = PyNumber_ToBase(val, 10);
222
24
        break;
223
44.3k
    case 'o':
224
44.3k
        numnondigits = 2;
225
44.3k
        result = PyNumber_ToBase(val, 8);
226
44.3k
        break;
227
63
    case 'x':
228
4.64M
    case 'X':
229
4.64M
        numnondigits = 2;
230
4.64M
        result = PyNumber_ToBase(val, 16);
231
4.64M
        break;
232
4.68M
    }
233
4.68M
    if (!result)
234
0
        return NULL;
235
236
4.68M
    assert(_PyUnicode_IsModifiable(result));
237
4.68M
    assert(PyUnicode_IS_ASCII(result));
238
239
    /* To modify the string in-place, there can only be one reference. */
240
4.68M
    if (!_PyObject_IsUniquelyReferenced(result)) {
241
0
        Py_DECREF(result);
242
0
        PyErr_BadInternalCall();
243
0
        return NULL;
244
0
    }
245
4.68M
    buf = PyUnicode_DATA(result);
246
4.68M
    llen = PyUnicode_GET_LENGTH(result);
247
4.68M
    if (llen > INT_MAX) {
248
0
        Py_DECREF(result);
249
0
        PyErr_SetString(PyExc_ValueError,
250
0
                        "string too large in _PyUnicode_FormatLong");
251
0
        return NULL;
252
0
    }
253
4.68M
    len = (int)llen;
254
4.68M
    sign = buf[0] == '-';
255
4.68M
    numnondigits += sign;
256
4.68M
    numdigits = len - numnondigits;
257
4.68M
    assert(numdigits > 0);
258
259
    /* Get rid of base marker unless F_ALT */
260
4.68M
    if (((alt) == 0 &&
261
4.68M
        (type == 'o' || type == 'x' || type == 'X'))) {
262
4.68M
        assert(buf[sign] == '0');
263
4.68M
        assert(buf[sign+1] == 'x' || buf[sign+1] == 'X' ||
264
4.68M
               buf[sign+1] == 'o');
265
4.68M
        numnondigits -= 2;
266
4.68M
        buf += 2;
267
4.68M
        len -= 2;
268
4.68M
        if (sign)
269
0
            buf[0] = '-';
270
4.68M
        assert(len == numnondigits + numdigits);
271
4.68M
        assert(numdigits > 0);
272
4.68M
    }
273
274
    /* Fill with leading zeroes to meet minimum width. */
275
4.68M
    if (prec > numdigits) {
276
0
        PyObject *r1 = PyBytes_FromStringAndSize(NULL,
277
0
                                numnondigits + prec);
278
0
        char *b1;
279
0
        if (!r1) {
280
0
            Py_DECREF(result);
281
0
            return NULL;
282
0
        }
283
0
        b1 = PyBytes_AS_STRING(r1);
284
0
        for (i = 0; i < numnondigits; ++i)
285
0
            *b1++ = *buf++;
286
0
        for (i = 0; i < prec - numdigits; i++)
287
0
            *b1++ = '0';
288
0
        for (i = 0; i < numdigits; i++)
289
0
            *b1++ = *buf++;
290
0
        *b1 = '\0';
291
0
        Py_SETREF(result, r1);
292
0
        buf = PyBytes_AS_STRING(result);
293
0
        len = numnondigits + prec;
294
0
    }
295
296
    /* Fix up case for hex conversions. */
297
4.68M
    if (type == 'X') {
298
        /* Need to convert all lower case letters to upper case.
299
           and need to convert 0x to 0X (and -0x to -0X). */
300
32.3M
        for (i = 0; i < len; i++)
301
27.7M
            if (buf[i] >= 'a' && buf[i] <= 'x')
302
5.94M
                buf[i] -= 'a'-'A';
303
4.64M
    }
304
4.68M
    if (!PyUnicode_Check(result)
305
4.68M
        || buf != PyUnicode_DATA(result)) {
306
4.68M
        PyObject *unicode;
307
4.68M
        unicode = _PyUnicode_FromASCII(buf, len);
308
4.68M
        Py_SETREF(result, unicode);
309
4.68M
    }
310
24
    else if (len != PyUnicode_GET_LENGTH(result)) {
311
0
        if (PyUnicode_Resize(&result, len) < 0)
312
0
            Py_CLEAR(result);
313
0
    }
314
4.68M
    return result;
315
4.68M
}
316
317
318
/* Format an integer or a float as an integer.
319
 * Return 1 if the number has been formatted into the writer,
320
 *        0 if the number has been formatted into *p_output
321
 *       -1 and raise an exception on error */
322
static int
323
mainformatlong(PyObject *v,
324
               struct unicode_formatter_t *ctx,
325
               struct unicode_format_arg_t *arg,
326
               PyObject **p_output,
327
               _PyUnicodeWriter *writer)
328
7.45M
{
329
7.45M
    PyObject *iobj, *res;
330
7.45M
    char type = (char)arg->ch;
331
332
7.45M
    if (!PyNumber_Check(v))
333
850k
        goto wrongtype;
334
335
    /* make sure number is a type of integer for o, x, and X */
336
6.60M
    if (!PyLong_Check(v)) {
337
0
        if (type == 'o' || type == 'x' || type == 'X') {
338
0
            iobj = _PyNumber_Index(v);
339
0
        }
340
0
        else {
341
0
            iobj = PyNumber_Long(v);
342
0
        }
343
0
        if (iobj == NULL ) {
344
0
            if (PyErr_ExceptionMatches(PyExc_TypeError))
345
0
                goto wrongtype;
346
0
            return -1;
347
0
        }
348
0
        assert(PyLong_Check(iobj));
349
0
    }
350
6.60M
    else {
351
6.60M
        iobj = Py_NewRef(v);
352
6.60M
    }
353
354
6.60M
    if (PyLong_CheckExact(v)
355
6.60M
        && arg->width == -1 && arg->prec == -1
356
6.55M
        && !(arg->flags & (F_SIGN | F_BLANK))
357
6.55M
        && type != 'X')
358
1.92M
    {
359
        /* Fast path */
360
1.92M
        int alternate = arg->flags & F_ALT;
361
1.92M
        int base;
362
363
1.92M
        switch(type)
364
1.92M
        {
365
0
            default:
366
0
                Py_UNREACHABLE();
367
1.92M
            case 'd':
368
1.92M
            case 'i':
369
1.92M
            case 'u':
370
1.92M
                base = 10;
371
1.92M
                break;
372
0
            case 'o':
373
0
                base = 8;
374
0
                break;
375
42
            case 'x':
376
42
            case 'X':
377
42
                base = 16;
378
42
                break;
379
1.92M
        }
380
381
1.92M
        if (_PyLong_FormatWriter(writer, v, base, alternate) == -1) {
382
0
            Py_DECREF(iobj);
383
0
            return -1;
384
0
        }
385
1.92M
        Py_DECREF(iobj);
386
1.92M
        return 1;
387
1.92M
    }
388
389
4.68M
    res = _PyUnicode_FormatLong(iobj, arg->flags & F_ALT, arg->prec, type);
390
4.68M
    Py_DECREF(iobj);
391
4.68M
    if (res == NULL)
392
0
        return -1;
393
4.68M
    *p_output = res;
394
4.68M
    return 0;
395
396
850k
wrongtype:
397
850k
    switch(type)
398
850k
    {
399
0
        case 'o':
400
0
        case 'x':
401
0
        case 'X':
402
0
            FORMAT_ERROR(PyExc_TypeError,
403
0
                         "%%%c requires an integer, not %T",
404
0
                         arg->ch, v);
405
0
            break;
406
850k
        default:
407
850k
            FORMAT_ERROR(PyExc_TypeError,
408
850k
                         "%%%c requires a real number, not %T",
409
850k
                         arg->ch, v);
410
850k
            break;
411
850k
    }
412
850k
    return -1;
413
850k
}
414
415
416
static Py_UCS4
417
formatchar(PyObject *v,
418
           struct unicode_formatter_t *ctx,
419
           struct unicode_format_arg_t *arg)
420
0
{
421
    /* presume that the buffer is at least 3 characters long */
422
0
    if (PyUnicode_Check(v)) {
423
0
        if (PyUnicode_GET_LENGTH(v) == 1) {
424
0
            return PyUnicode_READ_CHAR(v, 0);
425
0
        }
426
0
        FORMAT_ERROR(PyExc_TypeError,
427
0
                     "%%c requires an integer or a unicode character, "
428
0
                     "not a string of length %zd",
429
0
                     PyUnicode_GET_LENGTH(v));
430
0
        return (Py_UCS4) -1;
431
0
    }
432
0
    else {
433
0
        int overflow;
434
0
        long x = PyLong_AsLongAndOverflow(v, &overflow);
435
0
        if (x == -1 && PyErr_Occurred()) {
436
0
            if (PyErr_ExceptionMatches(PyExc_TypeError)) {
437
0
                FORMAT_ERROR(PyExc_TypeError,
438
0
                             "%%c requires an integer or a unicode character, "
439
0
                             "not %T",
440
0
                             v);
441
0
            }
442
0
            return (Py_UCS4) -1;
443
0
        }
444
445
0
        if (x < 0 || x > MAX_UNICODE) {
446
            /* this includes an overflow in converting to C long */
447
0
            FORMAT_ERROR(PyExc_OverflowError,
448
0
                         "%%c argument not in range(0x110000)%s", "");
449
0
            return (Py_UCS4) -1;
450
0
        }
451
452
0
        return (Py_UCS4) x;
453
0
    }
454
0
}
455
456
457
/* Parse options of an argument: flags, width, precision.
458
   Handle also "%(name)" syntax.
459
460
   Return 0 if the argument has been formatted into arg->str.
461
   Return 1 if the argument has been written into ctx->writer,
462
   Raise an exception and return -1 on error. */
463
static int
464
unicode_format_arg_parse(struct unicode_formatter_t *ctx,
465
                         struct unicode_format_arg_t *arg)
466
21.1M
{
467
21.1M
#define FORMAT_READ(ctx) \
468
21.5M
        PyUnicode_READ((ctx)->fmtkind, (ctx)->fmtdata, (ctx)->fmtpos)
469
470
21.1M
    PyObject *v;
471
472
21.1M
    if (arg->ch == '(') {
473
        /* Get argument value from a dictionary. Example: "%(name)s". */
474
48.4k
        Py_ssize_t keystart;
475
48.4k
        Py_ssize_t keylen;
476
48.4k
        int pcount = 1;
477
478
48.4k
        if (ctx->dict == NULL) {
479
0
            PyErr_Format(PyExc_TypeError,
480
0
                         "format requires a mapping, not %T",
481
0
                         ctx->args);
482
0
            return -1;
483
0
        }
484
48.4k
        ++ctx->fmtpos;
485
48.4k
        --ctx->fmtcnt;
486
48.4k
        keystart = ctx->fmtpos;
487
        /* Skip over balanced parentheses */
488
435k
        while (pcount > 0 && --ctx->fmtcnt >= 0) {
489
387k
            arg->ch = FORMAT_READ(ctx);
490
387k
            if (arg->ch == ')')
491
48.4k
                --pcount;
492
338k
            else if (arg->ch == '(')
493
0
                ++pcount;
494
387k
            ctx->fmtpos++;
495
387k
        }
496
48.4k
        keylen = ctx->fmtpos - keystart - 1;
497
48.4k
        if (ctx->fmtcnt < 0 || pcount > 0) {
498
0
            PyErr_Format(PyExc_ValueError,
499
0
                         "stray %% or incomplete format key at position %zd",
500
0
                         arg->fmtstart);
501
0
            return -1;
502
0
        }
503
48.4k
        arg->key = PyUnicode_Substring(ctx->fmtstr,
504
48.4k
                                       keystart, keystart + keylen);
505
48.4k
        if (arg->key == NULL)
506
0
            return -1;
507
48.4k
        if (ctx->args_owned) {
508
34.5k
            ctx->args_owned = 0;
509
34.5k
            Py_DECREF(ctx->args);
510
34.5k
        }
511
48.4k
        ctx->args = PyObject_GetItem(ctx->dict, arg->key);
512
48.4k
        if (ctx->args == NULL)
513
0
            return -1;
514
48.4k
        ctx->args_owned = 1;
515
48.4k
        ctx->arglen = -3;
516
48.4k
        ctx->argidx = -4;
517
48.4k
    }
518
21.0M
    else {
519
21.0M
        if (ctx->arglen < -1) {
520
0
            PyErr_Format(PyExc_ValueError,
521
0
                         "format requires a parenthesised mapping key "
522
0
                         "at position %zd",
523
0
                         arg->fmtstart);
524
0
            return -1;
525
0
        }
526
21.0M
    }
527
528
    /* Parse flags. Example: "%+i" => flags=F_SIGN. */
529
21.1M
    while (--ctx->fmtcnt >= 0) {
530
21.1M
        arg->ch = FORMAT_READ(ctx);
531
21.1M
        ctx->fmtpos++;
532
21.1M
        switch (arg->ch) {
533
0
        case '-': arg->flags |= F_LJUST; continue;
534
0
        case '+': arg->flags |= F_SIGN; continue;
535
0
        case ' ': arg->flags |= F_BLANK; continue;
536
42
        case '#': arg->flags |= F_ALT; continue;
537
45.4k
        case '0': arg->flags |= F_ZERO; continue;
538
21.1M
        }
539
21.1M
        break;
540
21.1M
    }
541
542
    /* Parse width. Example: "%10s" => width=10 */
543
21.1M
    if (arg->ch == '*') {
544
36.6k
        if (ctx->arglen < -1) {
545
0
            PyErr_Format(PyExc_ValueError,
546
0
                    "* cannot be used with a parenthesised mapping key "
547
0
                    "at position %zd",
548
0
                    arg->fmtstart);
549
0
            return -1;
550
0
        }
551
36.6k
        v = unicode_format_getnextarg(ctx, 0);
552
36.6k
        if (v == NULL)
553
0
            return -1;
554
36.6k
        if (!PyLong_Check(v)) {
555
0
            FORMAT_ERROR(PyExc_TypeError, "* requires int, not %T", v);
556
0
            return -1;
557
0
        }
558
36.6k
        arg->width = PyLong_AsSsize_t(v);
559
36.6k
        if (arg->width == -1 && PyErr_Occurred()) {
560
0
            if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
561
0
                FORMAT_ERROR(PyExc_OverflowError,
562
0
                             "too big for width%s", "");
563
0
            }
564
0
            return -1;
565
0
        }
566
36.6k
        if (arg->width < 0) {
567
0
            if (arg->width == PY_SSIZE_T_MIN) {
568
0
                FORMAT_ERROR(PyExc_OverflowError, "too big for width%s", "");
569
0
                return -1;
570
0
            }
571
0
            arg->flags |= F_LJUST;
572
0
            arg->width = -arg->width;
573
0
        }
574
36.6k
        if (--ctx->fmtcnt >= 0) {
575
36.6k
            arg->ch = FORMAT_READ(ctx);
576
36.6k
            ctx->fmtpos++;
577
36.6k
        }
578
36.6k
        assert(arg->width >= 0);
579
36.6k
    }
580
21.0M
    else if (arg->ch >= '0' && arg->ch <= '9') {
581
8.84k
        arg->width = arg->ch - '0';
582
8.84k
        while (--ctx->fmtcnt >= 0) {
583
8.84k
            arg->ch = FORMAT_READ(ctx);
584
8.84k
            ctx->fmtpos++;
585
8.84k
            if (arg->ch < '0' || arg->ch > '9')
586
8.84k
                break;
587
            /* Since arg->ch is unsigned, the RHS would end up as unsigned,
588
               mixing signed and unsigned comparison. Since arg->ch is between
589
               '0' and '9', casting to int is safe. */
590
0
            if (arg->width > (PY_SSIZE_T_MAX - ((int)arg->ch - '0')) / 10) {
591
0
                PyErr_Format(PyExc_ValueError,
592
0
                             "width too big at position %zd",
593
0
                             arg->fmtstart);
594
0
                return -1;
595
0
            }
596
0
            arg->width = arg->width*10 + (arg->ch - '0');
597
0
        }
598
8.84k
        assert(arg->width >= 0);
599
8.84k
    }
600
601
    /* Parse precision. Example: "%.3f" => prec=3 */
602
21.1M
    if (arg->ch == '.') {
603
93
        arg->prec = 0;
604
93
        if (--ctx->fmtcnt >= 0) {
605
93
            arg->ch = FORMAT_READ(ctx);
606
93
            ctx->fmtpos++;
607
93
        }
608
93
        if (arg->ch == '*') {
609
0
            if (ctx->arglen < -1) {
610
0
                PyErr_Format(PyExc_ValueError,
611
0
                        "* cannot be used with a parenthesised mapping key "
612
0
                        "at position %zd",
613
0
                        arg->fmtstart);
614
0
                return -1;
615
0
            }
616
0
            v = unicode_format_getnextarg(ctx, 0);
617
0
            if (v == NULL)
618
0
                return -1;
619
0
            if (!PyLong_Check(v)) {
620
0
                FORMAT_ERROR(PyExc_TypeError, "* requires int, not %T", v);
621
0
                return -1;
622
0
            }
623
0
            arg->prec = PyLong_AsInt(v);
624
0
            if (arg->prec == -1 && PyErr_Occurred()) {
625
0
                if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
626
0
                    FORMAT_ERROR(PyExc_OverflowError,
627
0
                                 "too big for precision%s", "");
628
0
                }
629
0
                return -1;
630
0
            }
631
0
            if (arg->prec < 0)
632
0
                arg->prec = 0;
633
0
            if (--ctx->fmtcnt >= 0) {
634
0
                arg->ch = FORMAT_READ(ctx);
635
0
                ctx->fmtpos++;
636
0
            }
637
0
        }
638
93
        else if (arg->ch >= '0' && arg->ch <= '9') {
639
93
            arg->prec = arg->ch - '0';
640
93
            while (--ctx->fmtcnt >= 0) {
641
93
                arg->ch = FORMAT_READ(ctx);
642
93
                ctx->fmtpos++;
643
93
                if (arg->ch < '0' || arg->ch > '9')
644
93
                    break;
645
0
                if (arg->prec > (INT_MAX - ((int)arg->ch - '0')) / 10) {
646
0
                    PyErr_Format(PyExc_ValueError,
647
0
                                 "precision too big at position %zd",
648
0
                                 arg->fmtstart);
649
0
                    return -1;
650
0
                }
651
0
                arg->prec = arg->prec*10 + (arg->ch - '0');
652
0
            }
653
93
        }
654
93
        assert(arg->prec >= 0);
655
93
    }
656
657
    /* Ignore "h", "l" and "L" format prefix (ex: "%hi" or "%ls") */
658
21.1M
    if (ctx->fmtcnt >= 0) {
659
21.1M
        if (arg->ch == 'h' || arg->ch == 'l' || arg->ch == 'L') {
660
0
            if (--ctx->fmtcnt >= 0) {
661
0
                arg->ch = FORMAT_READ(ctx);
662
0
                ctx->fmtpos++;
663
0
            }
664
0
        }
665
21.1M
    }
666
21.1M
    if (ctx->fmtcnt < 0) {
667
0
        PyErr_Format(PyExc_ValueError,
668
0
                     "stray %% at position %zd", arg->fmtstart);
669
0
        return -1;
670
0
    }
671
21.1M
    return 0;
672
673
21.1M
#undef FORMAT_READ
674
21.1M
}
675
676
677
/* Format one argument. Supported conversion specifiers:
678
679
   - "s", "r", "a": any type
680
   - "i", "d", "u": int or float
681
   - "o", "x", "X": int
682
   - "e", "E", "f", "F", "g", "G": float
683
   - "c": int or str (1 character)
684
685
   When possible, the output is written directly into the Unicode writer
686
   (ctx->writer). A string is created when padding is required.
687
688
   Return 0 if the argument has been formatted into *p_str,
689
          1 if the argument has been written into ctx->writer,
690
         -1 on error. */
691
static int
692
unicode_format_arg_format(struct unicode_formatter_t *ctx,
693
                          struct unicode_format_arg_t *arg,
694
                          PyObject **p_str)
695
21.1M
{
696
21.1M
    PyObject *v;
697
21.1M
    _PyUnicodeWriter *writer = &ctx->writer;
698
699
21.1M
    if (ctx->fmtcnt == 0)
700
7.37M
        ctx->writer.overallocate = 0;
701
702
21.1M
    v = unicode_format_getnextarg(ctx, 1);
703
21.1M
    if (v == NULL)
704
0
        return -1;
705
706
707
21.1M
    switch (arg->ch) {
708
13.6M
    case 's':
709
13.6M
    case 'r':
710
13.6M
    case 'a':
711
13.6M
        if (arg->width < 0 && arg->prec < 0) {
712
13.6M
            if (arg->ch == 's') {
713
13.6M
                if (PyUnicodeWriter_WriteStr((PyUnicodeWriter*)writer, v) < 0) {
714
0
                    return -1;
715
0
                }
716
13.6M
                return 1;
717
13.6M
            }
718
10.7k
            else if (arg->ch == 'r') {
719
10.7k
                if (PyUnicodeWriter_WriteRepr((PyUnicodeWriter*)writer, v) < 0) {
720
0
                    return -1;
721
0
                }
722
10.7k
                return 1;
723
10.7k
            }
724
13.6M
        }
725
726
0
        if (arg->ch == 's')
727
0
            *p_str = PyObject_Str(v);
728
0
        else if (arg->ch == 'r')
729
0
            *p_str = PyObject_Repr(v);
730
0
        else
731
0
            *p_str = PyObject_ASCII(v);
732
0
        break;
733
734
0
    case 'i':
735
2.77M
    case 'd':
736
2.77M
    case 'u':
737
2.81M
    case 'o':
738
2.81M
    case 'x':
739
7.45M
    case 'X':
740
7.45M
    {
741
7.45M
        int ret = mainformatlong(v, ctx, arg, p_str, writer);
742
7.45M
        if (ret != 0)
743
2.77M
            return ret;
744
4.68M
        arg->sign = 1;
745
4.68M
        break;
746
7.45M
    }
747
748
0
    case 'e':
749
0
    case 'E':
750
93
    case 'f':
751
93
    case 'F':
752
93
    case 'g':
753
93
    case 'G':
754
93
        if (arg->width == -1 && arg->prec == -1
755
0
            && !(arg->flags & (F_SIGN | F_BLANK)))
756
0
        {
757
            /* Fast path */
758
0
            if (formatfloat(v, ctx, arg, NULL, writer) == -1)
759
0
                return -1;
760
0
            return 1;
761
0
        }
762
763
93
        arg->sign = 1;
764
93
        if (formatfloat(v, ctx, arg, p_str, NULL) == -1)
765
0
            return -1;
766
93
        break;
767
768
93
    case 'c':
769
0
    {
770
0
        Py_UCS4 ch = formatchar(v, ctx, arg);
771
0
        if (ch == (Py_UCS4) -1)
772
0
            return -1;
773
0
        if (arg->width == -1 && arg->prec == -1) {
774
            /* Fast path */
775
0
            if (_PyUnicodeWriter_WriteCharInline(writer, ch) < 0)
776
0
                return -1;
777
0
            return 1;
778
0
        }
779
0
        *p_str = PyUnicode_FromOrdinal(ch);
780
0
        break;
781
0
    }
782
783
0
    default:
784
0
        if (arg->ch < 128 && Py_ISALPHA(arg->ch)) {
785
0
            PyErr_Format(PyExc_ValueError,
786
0
                         "unsupported format %%%c at position %zd",
787
0
                         (int)arg->ch, arg->fmtstart);
788
0
        }
789
0
        else if (arg->ch == '\'') {
790
0
            PyErr_Format(PyExc_ValueError,
791
0
                         "stray %% at position %zd or unexpected "
792
0
                         "format character \"'\" at position %zd",
793
0
                         arg->fmtstart,
794
0
                         ctx->fmtpos - 1);
795
0
        }
796
0
        else if (arg->ch >= 32 && arg->ch < 127) {
797
0
            PyErr_Format(PyExc_ValueError,
798
0
                         "stray %% at position %zd or unexpected "
799
0
                         "format character '%c' at position %zd",
800
0
                         arg->fmtstart,
801
0
                         (int)arg->ch, ctx->fmtpos - 1);
802
0
        }
803
0
        else if (Py_UNICODE_ISPRINTABLE(arg->ch)) {
804
0
            PyErr_Format(PyExc_ValueError,
805
0
                         "stray %% at position %zd or unexpected "
806
0
                         "format character '%c' (U+%04X) at position %zd",
807
0
                         arg->fmtstart,
808
0
                         (int)arg->ch, (int)arg->ch, ctx->fmtpos - 1);
809
0
        }
810
0
        else {
811
0
            PyErr_Format(PyExc_ValueError,
812
0
                         "stray %% at position %zd or unexpected "
813
0
                         "format character U+%04X at position %zd",
814
0
                         arg->fmtstart, (int)arg->ch, ctx->fmtpos - 1);
815
0
        }
816
0
        return -1;
817
21.1M
    }
818
4.68M
    if (*p_str == NULL)
819
0
        return -1;
820
4.68M
    assert (PyUnicode_Check(*p_str));
821
4.68M
    return 0;
822
4.68M
}
823
824
825
static int
826
unicode_format_arg_output(struct unicode_formatter_t *ctx,
827
                          struct unicode_format_arg_t *arg,
828
                          PyObject *str)
829
4.68M
{
830
4.68M
    Py_ssize_t len;
831
4.68M
    int kind;
832
4.68M
    const void *pbuf;
833
4.68M
    Py_ssize_t pindex;
834
4.68M
    Py_UCS4 signchar;
835
4.68M
    Py_ssize_t buflen;
836
4.68M
    Py_UCS4 maxchar;
837
4.68M
    Py_ssize_t sublen;
838
4.68M
    _PyUnicodeWriter *writer = &ctx->writer;
839
4.68M
    Py_UCS4 fill;
840
841
4.68M
    fill = ' ';
842
4.68M
    if (arg->sign && arg->flags & F_ZERO)
843
45.4k
        fill = '0';
844
845
4.68M
    len = PyUnicode_GET_LENGTH(str);
846
4.68M
    if ((arg->width == -1 || arg->width <= len)
847
4.64M
        && (arg->prec == -1 || arg->prec >= len)
848
4.64M
        && !(arg->flags & (F_SIGN | F_BLANK)))
849
4.64M
    {
850
        /* Fast path */
851
4.64M
        if (_PyUnicodeWriter_WriteStr(writer, str) == -1)
852
0
            return -1;
853
4.64M
        return 0;
854
4.64M
    }
855
856
    /* Truncate the string for "s", "r" and "a" formats
857
       if the precision is set */
858
44.5k
    if (arg->ch == 's' || arg->ch == 'r' || arg->ch == 'a') {
859
0
        if (arg->prec >= 0 && len > arg->prec)
860
0
            len = arg->prec;
861
0
    }
862
863
    /* Adjust sign and width */
864
44.5k
    kind = PyUnicode_KIND(str);
865
44.5k
    pbuf = PyUnicode_DATA(str);
866
44.5k
    pindex = 0;
867
44.5k
    signchar = '\0';
868
44.5k
    if (arg->sign) {
869
44.5k
        Py_UCS4 ch = PyUnicode_READ(kind, pbuf, pindex);
870
44.5k
        if (ch == '-' || ch == '+') {
871
0
            signchar = ch;
872
0
            len--;
873
0
            pindex++;
874
0
        }
875
44.5k
        else if (arg->flags & F_SIGN)
876
0
            signchar = '+';
877
44.5k
        else if (arg->flags & F_BLANK)
878
0
            signchar = ' ';
879
44.5k
        else
880
44.5k
            arg->sign = 0;
881
44.5k
    }
882
44.5k
    if (arg->width < len)
883
93
        arg->width = len;
884
885
    /* Prepare the writer */
886
44.5k
    maxchar = writer->maxchar;
887
44.5k
    if (!(arg->flags & F_LJUST)) {
888
44.5k
        if (arg->sign) {
889
0
            if ((arg->width-1) > len)
890
0
                maxchar = Py_MAX(maxchar, fill);
891
0
        }
892
44.5k
        else {
893
44.5k
            if (arg->width > len)
894
44.4k
                maxchar = Py_MAX(maxchar, fill);
895
44.5k
        }
896
44.5k
    }
897
44.5k
    if (PyUnicode_MAX_CHAR_VALUE(str) > maxchar) {
898
44.3k
        Py_UCS4 strmaxchar = _PyUnicode_FindMaxChar(str, 0, pindex+len);
899
44.3k
        maxchar = Py_MAX(maxchar, strmaxchar);
900
44.3k
    }
901
902
44.5k
    buflen = arg->width;
903
44.5k
    if (arg->sign && len == arg->width)
904
0
        buflen++;
905
44.5k
    if (_PyUnicodeWriter_Prepare(writer, buflen, maxchar) == -1)
906
0
        return -1;
907
908
    /* Write the sign if needed */
909
44.5k
    if (arg->sign) {
910
0
        if (fill != ' ') {
911
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar);
912
0
            writer->pos += 1;
913
0
        }
914
0
        if (arg->width > len)
915
0
            arg->width--;
916
0
    }
917
918
    /* Write the numeric prefix for "x", "X" and "o" formats
919
       if the alternate form is used.
920
       For example, write "0x" for the "%#x" format. */
921
44.5k
    if ((arg->flags & F_ALT) && (arg->ch == 'x' || arg->ch == 'X' || arg->ch == 'o')) {
922
0
        assert(PyUnicode_READ(kind, pbuf, pindex) == '0');
923
0
        assert(PyUnicode_READ(kind, pbuf, pindex + 1) == arg->ch);
924
0
        if (fill != ' ') {
925
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, '0');
926
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos+1, arg->ch);
927
0
            writer->pos += 2;
928
0
            pindex += 2;
929
0
        }
930
0
        arg->width -= 2;
931
0
        if (arg->width < 0)
932
0
            arg->width = 0;
933
0
        len -= 2;
934
0
    }
935
936
    /* Pad left with the fill character if needed */
937
44.5k
    if (arg->width > len && !(arg->flags & F_LJUST)) {
938
44.4k
        sublen = arg->width - len;
939
44.4k
        _PyUnicode_Fill(writer->kind, writer->data, fill, writer->pos, sublen);
940
44.4k
        writer->pos += sublen;
941
44.4k
        arg->width = len;
942
44.4k
    }
943
944
    /* If padding with spaces: write sign if needed and/or numeric prefix if
945
       the alternate form is used */
946
44.5k
    if (fill == ' ') {
947
93
        if (arg->sign) {
948
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar);
949
0
            writer->pos += 1;
950
0
        }
951
93
        if ((arg->flags & F_ALT) && (arg->ch == 'x' || arg->ch == 'X' || arg->ch == 'o')) {
952
0
            assert(PyUnicode_READ(kind, pbuf, pindex) == '0');
953
0
            assert(PyUnicode_READ(kind, pbuf, pindex+1) == arg->ch);
954
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, '0');
955
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos+1, arg->ch);
956
0
            writer->pos += 2;
957
0
            pindex += 2;
958
0
        }
959
93
    }
960
961
    /* Write characters */
962
44.5k
    if (len) {
963
44.5k
        _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
964
44.5k
                                      str, pindex, len);
965
44.5k
        writer->pos += len;
966
44.5k
    }
967
968
    /* Pad right with the fill character if needed */
969
44.5k
    if (arg->width > len) {
970
0
        sublen = arg->width - len;
971
0
        _PyUnicode_Fill(writer->kind, writer->data, ' ', writer->pos, sublen);
972
0
        writer->pos += sublen;
973
0
    }
974
44.5k
    return 0;
975
44.5k
}
976
977
978
/* Helper of PyUnicode_Format(): format one arg.
979
   Return 0 on success, raise an exception and return -1 on error. */
980
static int
981
unicode_format_arg(struct unicode_formatter_t *ctx)
982
21.1M
{
983
21.1M
    struct unicode_format_arg_t arg;
984
21.1M
    PyObject *str;
985
21.1M
    int ret;
986
987
21.1M
    arg.ch = PyUnicode_READ(ctx->fmtkind, ctx->fmtdata, ctx->fmtpos);
988
21.1M
    if (arg.ch == '%') {
989
0
        ctx->fmtpos++;
990
0
        ctx->fmtcnt--;
991
0
        if (_PyUnicodeWriter_WriteCharInline(&ctx->writer, '%') < 0)
992
0
            return -1;
993
0
        return 0;
994
0
    }
995
21.1M
    arg.flags = 0;
996
21.1M
    arg.width = -1;
997
21.1M
    arg.prec = -1;
998
21.1M
    arg.sign = 0;
999
21.1M
    arg.fmtstart = ctx->fmtpos - 1;
1000
21.1M
    arg.key = NULL;
1001
21.1M
    str = NULL;
1002
1003
21.1M
    ret = unicode_format_arg_parse(ctx, &arg);
1004
21.1M
    if (ret == -1) {
1005
0
        goto onError;
1006
0
    }
1007
1008
21.1M
    ret = unicode_format_arg_format(ctx, &arg, &str);
1009
21.1M
    if (ret == -1) {
1010
850k
        goto onError;
1011
850k
    }
1012
1013
20.2M
    if (ret != 1) {
1014
4.68M
        ret = unicode_format_arg_output(ctx, &arg, str);
1015
4.68M
        Py_DECREF(str);
1016
4.68M
        if (ret == -1) {
1017
0
            goto onError;
1018
0
        }
1019
4.68M
    }
1020
1021
20.2M
    if (ctx->dict && (ctx->argidx < ctx->arglen)) {
1022
        // XXX: Never happens?
1023
0
        PyErr_SetString(PyExc_TypeError,
1024
0
                        "not all arguments converted during string formatting");
1025
0
        goto onError;
1026
0
    }
1027
20.2M
    Py_XDECREF(arg.key);
1028
20.2M
    return 0;
1029
1030
850k
  onError:
1031
850k
    Py_XDECREF(arg.key);
1032
850k
    return -1;
1033
20.2M
}
1034
1035
1036
PyObject *
1037
PyUnicode_Format(PyObject *format, PyObject *args)
1038
12.3M
{
1039
12.3M
    struct unicode_formatter_t ctx;
1040
1041
12.3M
    if (format == NULL || args == NULL) {
1042
0
        PyErr_BadInternalCall();
1043
0
        return NULL;
1044
0
    }
1045
1046
12.3M
    if (ensure_unicode(format) < 0)
1047
0
        return NULL;
1048
1049
12.3M
    ctx.fmtstr = format;
1050
12.3M
    ctx.fmtdata = PyUnicode_DATA(ctx.fmtstr);
1051
12.3M
    ctx.fmtkind = PyUnicode_KIND(ctx.fmtstr);
1052
12.3M
    ctx.fmtcnt = PyUnicode_GET_LENGTH(ctx.fmtstr);
1053
12.3M
    ctx.fmtpos = 0;
1054
1055
12.3M
    _PyUnicodeWriter_Init(&ctx.writer);
1056
12.3M
    ctx.writer.min_length = ctx.fmtcnt + 100;
1057
12.3M
    ctx.writer.overallocate = 1;
1058
1059
12.3M
    if (PyTuple_Check(args)) {
1060
5.72M
        ctx.arglen = PyTuple_Size(args);
1061
5.72M
        ctx.argidx = 0;
1062
5.72M
    }
1063
6.67M
    else {
1064
6.67M
        ctx.arglen = -1;
1065
6.67M
        ctx.argidx = -2;
1066
6.67M
    }
1067
12.3M
    ctx.args_owned = 0;
1068
12.3M
    if (PyMapping_Check(args) && !PyTuple_Check(args) && !PyUnicode_Check(args))
1069
14.6k
        ctx.dict = args;
1070
12.3M
    else
1071
12.3M
        ctx.dict = NULL;
1072
12.3M
    ctx.args = args;
1073
1074
56.7M
    while (--ctx.fmtcnt >= 0) {
1075
45.1M
        if (PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') {
1076
24.0M
            Py_ssize_t nonfmtpos;
1077
1078
24.0M
            nonfmtpos = ctx.fmtpos++;
1079
144M
            while (ctx.fmtcnt >= 0 &&
1080
139M
                   PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') {
1081
120M
                ctx.fmtpos++;
1082
120M
                ctx.fmtcnt--;
1083
120M
            }
1084
24.0M
            if (ctx.fmtcnt < 0) {
1085
5.02M
                ctx.fmtpos--;
1086
5.02M
                ctx.writer.overallocate = 0;
1087
5.02M
            }
1088
1089
24.0M
            if (_PyUnicodeWriter_WriteSubstring(&ctx.writer, ctx.fmtstr,
1090
24.0M
                                                nonfmtpos, ctx.fmtpos) < 0)
1091
0
                goto onError;
1092
24.0M
        }
1093
21.1M
        else {
1094
21.1M
            ctx.fmtpos++;
1095
21.1M
            if (unicode_format_arg(&ctx) == -1)
1096
850k
                goto onError;
1097
21.1M
        }
1098
45.1M
    }
1099
1100
11.5M
    if (ctx.argidx < ctx.arglen && !ctx.dict) {
1101
0
        PyErr_Format(PyExc_TypeError,
1102
0
                     "not all arguments converted during string formatting "
1103
0
                     "(required %zd, got %zd)",
1104
0
                     ctx.arglen < 0 ? 0 : ctx.argidx,
1105
0
                     ctx.arglen < 0 ? 1 : ctx.arglen);
1106
0
        goto onError;
1107
0
    }
1108
1109
11.5M
    if (ctx.args_owned) {
1110
13.8k
        Py_DECREF(ctx.args);
1111
13.8k
    }
1112
11.5M
    return _PyUnicodeWriter_Finish(&ctx.writer);
1113
1114
850k
  onError:
1115
850k
    _PyUnicodeWriter_Dealloc(&ctx.writer);
1116
850k
    if (ctx.args_owned) {
1117
0
        Py_DECREF(ctx.args);
1118
0
    }
1119
    return NULL;
1120
11.5M
}