Coverage Report

Created: 2026-07-14 06:16

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.1M
#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
950k
#define FORMAT_ERROR(EXC, FMT, ...) do {                                    \
82
950k
    if (arg->key != NULL) {                                                 \
83
0
        PyErr_Format((EXC), "format argument %R: " FMT,                     \
84
0
                     arg->key, __VA_ARGS__);                                \
85
0
    }                                                                       \
86
950k
    else if (ctx->argidx >= 0) {                                            \
87
0
        PyErr_Format((EXC), "format argument %zd: " FMT,                    \
88
0
                     ctx->argidx, __VA_ARGS__);                             \
89
0
    }                                                                       \
90
950k
    else {                                                                  \
91
950k
        PyErr_Format((EXC), "format argument: " FMT, __VA_ARGS__);          \
92
950k
    }                                                                       \
93
950k
} while (0)
94
95
96
static PyObject *
97
unicode_format_getnextarg(struct unicode_formatter_t *ctx, int allowone)
98
21.8M
{
99
21.8M
    Py_ssize_t argidx = ctx->argidx;
100
101
21.8M
    if (argidx < ctx->arglen && (allowone || ctx->arglen >= 0)) {
102
21.8M
        ctx->argidx++;
103
21.8M
        if (ctx->arglen >= 0) {
104
16.0M
            return PyTuple_GetItem(ctx->args, argidx);
105
16.0M
        }
106
5.84M
        else if (allowone) {
107
5.84M
            return ctx->args;
108
5.84M
        }
109
21.8M
    }
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.8M
}
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
95
{
130
95
    char *p;
131
95
    double x;
132
95
    Py_ssize_t len;
133
95
    int prec;
134
95
    int dtoa_flags = 0;
135
136
95
    x = PyFloat_AsDouble(v);
137
95
    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
95
    prec = arg->prec;
147
95
    if (prec < 0)
148
0
        prec = 6;
149
150
95
    if (arg->flags & F_ALT)
151
0
        dtoa_flags |= Py_DTSF_ALT;
152
95
    p = PyOS_double_to_string(x, arg->ch, prec, dtoa_flags, NULL);
153
95
    if (p == NULL)
154
0
        return -1;
155
95
    len = strlen(p);
156
95
    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
95
    else {
163
95
        *p_output = _PyUnicode_FromASCII(p, len);
164
95
        if (*p_output == NULL) {
165
0
            PyMem_Free(p);
166
0
            return -1;
167
0
        }
168
95
    }
169
95
    PyMem_Free(p);
170
95
    return 0;
171
95
}
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
5.22M
{
195
5.22M
    PyObject *result = NULL;
196
5.22M
    char *buf;
197
5.22M
    Py_ssize_t i;
198
5.22M
    int sign;           /* 1 if '-', else 0 */
199
5.22M
    int len;            /* number of characters */
200
5.22M
    Py_ssize_t llen;
201
5.22M
    int numdigits;      /* len == numnondigits + numdigits */
202
5.22M
    int numnondigits = 0;
203
204
    /* Avoid exceeding SSIZE_T_MAX */
205
5.22M
    if (prec > INT_MAX-3) {
206
0
        PyErr_SetString(PyExc_OverflowError,
207
0
                        "precision too large");
208
0
        return NULL;
209
0
    }
210
211
5.22M
    assert(PyLong_Check(val));
212
213
5.22M
    switch (type) {
214
0
    default:
215
0
        Py_UNREACHABLE();
216
36
    case 'd':
217
36
    case 'i':
218
36
    case 'u':
219
        /* int and int subclasses should print numerically when a numeric */
220
        /* format code is used (see issue18780) */
221
36
        result = PyNumber_ToBase(val, 10);
222
36
        break;
223
77.5k
    case 'o':
224
77.5k
        numnondigits = 2;
225
77.5k
        result = PyNumber_ToBase(val, 8);
226
77.5k
        break;
227
65
    case 'x':
228
5.14M
    case 'X':
229
5.14M
        numnondigits = 2;
230
5.14M
        result = PyNumber_ToBase(val, 16);
231
5.14M
        break;
232
5.22M
    }
233
5.22M
    if (!result)
234
0
        return NULL;
235
236
5.22M
    assert(_PyUnicode_IsModifiable(result));
237
5.22M
    assert(PyUnicode_IS_ASCII(result));
238
239
    /* To modify the string in-place, there can only be one reference. */
240
5.22M
    if (!_PyObject_IsUniquelyReferenced(result)) {
241
0
        Py_DECREF(result);
242
0
        PyErr_BadInternalCall();
243
0
        return NULL;
244
0
    }
245
5.22M
    buf = PyUnicode_DATA(result);
246
5.22M
    llen = PyUnicode_GET_LENGTH(result);
247
5.22M
    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
5.22M
    len = (int)llen;
254
5.22M
    sign = buf[0] == '-';
255
5.22M
    numnondigits += sign;
256
5.22M
    numdigits = len - numnondigits;
257
5.22M
    assert(numdigits > 0);
258
259
    /* Get rid of base marker unless F_ALT */
260
5.22M
    if (((alt) == 0 &&
261
5.22M
        (type == 'o' || type == 'x' || type == 'X'))) {
262
5.22M
        assert(buf[sign] == '0');
263
5.22M
        assert(buf[sign+1] == 'x' || buf[sign+1] == 'X' ||
264
5.22M
               buf[sign+1] == 'o');
265
5.22M
        numnondigits -= 2;
266
5.22M
        buf += 2;
267
5.22M
        len -= 2;
268
5.22M
        if (sign)
269
0
            buf[0] = '-';
270
5.22M
        assert(len == numnondigits + numdigits);
271
5.22M
        assert(numdigits > 0);
272
5.22M
    }
273
274
    /* Fill with leading zeroes to meet minimum width. */
275
5.22M
    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
5.22M
    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
35.8M
        for (i = 0; i < len; i++)
301
30.7M
            if (buf[i] >= 'a' && buf[i] <= 'x')
302
6.56M
                buf[i] -= 'a'-'A';
303
5.14M
    }
304
5.22M
    if (!PyUnicode_Check(result)
305
5.22M
        || buf != PyUnicode_DATA(result)) {
306
5.22M
        PyObject *unicode;
307
5.22M
        unicode = _PyUnicode_FromASCII(buf, len);
308
5.22M
        Py_SETREF(result, unicode);
309
5.22M
    }
310
36
    else if (len != PyUnicode_GET_LENGTH(result)) {
311
0
        if (PyUnicode_Resize(&result, len) < 0)
312
0
            Py_CLEAR(result);
313
0
    }
314
5.22M
    return result;
315
5.22M
}
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.68M
{
329
7.68M
    PyObject *iobj, *res;
330
7.68M
    char type = (char)arg->ch;
331
332
7.68M
    if (!PyNumber_Check(v))
333
950k
        goto wrongtype;
334
335
    /* make sure number is a type of integer for o, x, and X */
336
6.72M
    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.72M
    else {
351
6.72M
        iobj = Py_NewRef(v);
352
6.72M
    }
353
354
6.72M
    if (PyLong_CheckExact(v)
355
6.72M
        && arg->width == -1 && arg->prec == -1
356
6.64M
        && !(arg->flags & (F_SIGN | F_BLANK))
357
6.64M
        && type != 'X')
358
1.50M
    {
359
        /* Fast path */
360
1.50M
        int alternate = arg->flags & F_ALT;
361
1.50M
        int base;
362
363
1.50M
        switch(type)
364
1.50M
        {
365
0
            default:
366
0
                Py_UNREACHABLE();
367
1.50M
            case 'd':
368
1.50M
            case 'i':
369
1.50M
            case 'u':
370
1.50M
                base = 10;
371
1.50M
                break;
372
0
            case 'o':
373
0
                base = 8;
374
0
                break;
375
44
            case 'x':
376
44
            case 'X':
377
44
                base = 16;
378
44
                break;
379
1.50M
        }
380
381
1.50M
        if (_PyLong_FormatWriter(writer, v, base, alternate) == -1) {
382
0
            Py_DECREF(iobj);
383
0
            return -1;
384
0
        }
385
1.50M
        Py_DECREF(iobj);
386
1.50M
        return 1;
387
1.50M
    }
388
389
5.22M
    res = _PyUnicode_FormatLong(iobj, arg->flags & F_ALT, arg->prec, type);
390
5.22M
    Py_DECREF(iobj);
391
5.22M
    if (res == NULL)
392
0
        return -1;
393
5.22M
    *p_output = res;
394
5.22M
    return 0;
395
396
950k
wrongtype:
397
950k
    switch(type)
398
950k
    {
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
950k
        default:
407
950k
            FORMAT_ERROR(PyExc_TypeError,
408
950k
                         "%%%c requires a real number, not %T",
409
950k
                         arg->ch, v);
410
950k
            break;
411
950k
    }
412
950k
    return -1;
413
950k
}
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.8M
{
467
21.8M
#define FORMAT_READ(ctx) \
468
22.3M
        PyUnicode_READ((ctx)->fmtkind, (ctx)->fmtdata, (ctx)->fmtpos)
469
470
21.8M
    PyObject *v;
471
472
21.8M
    if (arg->ch == '(') {
473
        /* Get argument value from a dictionary. Example: "%(name)s". */
474
51.5k
        Py_ssize_t keystart;
475
51.5k
        Py_ssize_t keylen;
476
51.5k
        int pcount = 1;
477
478
51.5k
        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
51.5k
        ++ctx->fmtpos;
485
51.5k
        --ctx->fmtcnt;
486
51.5k
        keystart = ctx->fmtpos;
487
        /* Skip over balanced parentheses */
488
463k
        while (pcount > 0 && --ctx->fmtcnt >= 0) {
489
412k
            arg->ch = FORMAT_READ(ctx);
490
412k
            if (arg->ch == ')')
491
51.5k
                --pcount;
492
360k
            else if (arg->ch == '(')
493
0
                ++pcount;
494
412k
            ctx->fmtpos++;
495
412k
        }
496
51.5k
        keylen = ctx->fmtpos - keystart - 1;
497
51.5k
        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
51.5k
        arg->key = PyUnicode_Substring(ctx->fmtstr,
504
51.5k
                                       keystart, keystart + keylen);
505
51.5k
        if (arg->key == NULL)
506
0
            return -1;
507
51.5k
        if (ctx->args_owned) {
508
36.8k
            ctx->args_owned = 0;
509
36.8k
            Py_DECREF(ctx->args);
510
36.8k
        }
511
51.5k
        ctx->args = PyObject_GetItem(ctx->dict, arg->key);
512
51.5k
        if (ctx->args == NULL)
513
0
            return -1;
514
51.5k
        ctx->args_owned = 1;
515
51.5k
        ctx->arglen = -3;
516
51.5k
        ctx->argidx = -4;
517
51.5k
    }
518
21.7M
    else {
519
21.7M
        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.7M
    }
527
528
    /* Parse flags. Example: "%+i" => flags=F_SIGN. */
529
21.8M
    while (--ctx->fmtcnt >= 0) {
530
21.8M
        arg->ch = FORMAT_READ(ctx);
531
21.8M
        ctx->fmtpos++;
532
21.8M
        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
44
        case '#': arg->flags |= F_ALT; continue;
537
79.7k
        case '0': arg->flags |= F_ZERO; continue;
538
21.8M
        }
539
21.8M
        break;
540
21.8M
    }
541
542
    /* Parse width. Example: "%10s" => width=10 */
543
21.8M
    if (arg->ch == '*') {
544
64.2k
        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
64.2k
        v = unicode_format_getnextarg(ctx, 0);
552
64.2k
        if (v == NULL)
553
0
            return -1;
554
64.2k
        if (!PyLong_Check(v)) {
555
0
            FORMAT_ERROR(PyExc_TypeError, "* requires int, not %T", v);
556
0
            return -1;
557
0
        }
558
64.2k
        arg->width = PyLong_AsSsize_t(v);
559
64.2k
        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
64.2k
        if (arg->width < 0) {
567
0
            arg->flags |= F_LJUST;
568
0
            arg->width = -arg->width;
569
0
        }
570
64.2k
        if (--ctx->fmtcnt >= 0) {
571
64.2k
            arg->ch = FORMAT_READ(ctx);
572
64.2k
            ctx->fmtpos++;
573
64.2k
        }
574
64.2k
    }
575
21.7M
    else if (arg->ch >= '0' && arg->ch <= '9') {
576
15.4k
        arg->width = arg->ch - '0';
577
15.4k
        while (--ctx->fmtcnt >= 0) {
578
15.4k
            arg->ch = FORMAT_READ(ctx);
579
15.4k
            ctx->fmtpos++;
580
15.4k
            if (arg->ch < '0' || arg->ch > '9')
581
15.4k
                break;
582
            /* Since arg->ch is unsigned, the RHS would end up as unsigned,
583
               mixing signed and unsigned comparison. Since arg->ch is between
584
               '0' and '9', casting to int is safe. */
585
0
            if (arg->width > (PY_SSIZE_T_MAX - ((int)arg->ch - '0')) / 10) {
586
0
                PyErr_Format(PyExc_ValueError,
587
0
                             "width too big at position %zd",
588
0
                             arg->fmtstart);
589
0
                return -1;
590
0
            }
591
0
            arg->width = arg->width*10 + (arg->ch - '0');
592
0
        }
593
15.4k
    }
594
595
    /* Parse precision. Example: "%.3f" => prec=3 */
596
21.8M
    if (arg->ch == '.') {
597
95
        arg->prec = 0;
598
95
        if (--ctx->fmtcnt >= 0) {
599
95
            arg->ch = FORMAT_READ(ctx);
600
95
            ctx->fmtpos++;
601
95
        }
602
95
        if (arg->ch == '*') {
603
0
            if (ctx->arglen < -1) {
604
0
                PyErr_Format(PyExc_ValueError,
605
0
                        "* cannot be used with a parenthesised mapping key "
606
0
                        "at position %zd",
607
0
                        arg->fmtstart);
608
0
                return -1;
609
0
            }
610
0
            v = unicode_format_getnextarg(ctx, 0);
611
0
            if (v == NULL)
612
0
                return -1;
613
0
            if (!PyLong_Check(v)) {
614
0
                FORMAT_ERROR(PyExc_TypeError, "* requires int, not %T", v);
615
0
                return -1;
616
0
            }
617
0
            arg->prec = PyLong_AsInt(v);
618
0
            if (arg->prec == -1 && PyErr_Occurred()) {
619
0
                if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
620
0
                    FORMAT_ERROR(PyExc_OverflowError,
621
0
                                 "too big for precision%s", "");
622
0
                }
623
0
                return -1;
624
0
            }
625
0
            if (arg->prec < 0)
626
0
                arg->prec = 0;
627
0
            if (--ctx->fmtcnt >= 0) {
628
0
                arg->ch = FORMAT_READ(ctx);
629
0
                ctx->fmtpos++;
630
0
            }
631
0
        }
632
95
        else if (arg->ch >= '0' && arg->ch <= '9') {
633
95
            arg->prec = arg->ch - '0';
634
95
            while (--ctx->fmtcnt >= 0) {
635
95
                arg->ch = FORMAT_READ(ctx);
636
95
                ctx->fmtpos++;
637
95
                if (arg->ch < '0' || arg->ch > '9')
638
95
                    break;
639
0
                if (arg->prec > (INT_MAX - ((int)arg->ch - '0')) / 10) {
640
0
                    PyErr_Format(PyExc_ValueError,
641
0
                                 "precision too big at position %zd",
642
0
                                 arg->fmtstart);
643
0
                    return -1;
644
0
                }
645
0
                arg->prec = arg->prec*10 + (arg->ch - '0');
646
0
            }
647
95
        }
648
95
    }
649
650
    /* Ignore "h", "l" and "L" format prefix (ex: "%hi" or "%ls") */
651
21.8M
    if (ctx->fmtcnt >= 0) {
652
21.8M
        if (arg->ch == 'h' || arg->ch == 'l' || arg->ch == 'L') {
653
0
            if (--ctx->fmtcnt >= 0) {
654
0
                arg->ch = FORMAT_READ(ctx);
655
0
                ctx->fmtpos++;
656
0
            }
657
0
        }
658
21.8M
    }
659
21.8M
    if (ctx->fmtcnt < 0) {
660
0
        PyErr_Format(PyExc_ValueError,
661
0
                     "stray %% at position %zd", arg->fmtstart);
662
0
        return -1;
663
0
    }
664
21.8M
    return 0;
665
666
21.8M
#undef FORMAT_READ
667
21.8M
}
668
669
670
/* Format one argument. Supported conversion specifiers:
671
672
   - "s", "r", "a": any type
673
   - "i", "d", "u": int or float
674
   - "o", "x", "X": int
675
   - "e", "E", "f", "F", "g", "G": float
676
   - "c": int or str (1 character)
677
678
   When possible, the output is written directly into the Unicode writer
679
   (ctx->writer). A string is created when padding is required.
680
681
   Return 0 if the argument has been formatted into *p_str,
682
          1 if the argument has been written into ctx->writer,
683
         -1 on error. */
684
static int
685
unicode_format_arg_format(struct unicode_formatter_t *ctx,
686
                          struct unicode_format_arg_t *arg,
687
                          PyObject **p_str)
688
21.8M
{
689
21.8M
    PyObject *v;
690
21.8M
    _PyUnicodeWriter *writer = &ctx->writer;
691
692
21.8M
    if (ctx->fmtcnt == 0)
693
7.57M
        ctx->writer.overallocate = 0;
694
695
21.8M
    v = unicode_format_getnextarg(ctx, 1);
696
21.8M
    if (v == NULL)
697
0
        return -1;
698
699
700
21.8M
    switch (arg->ch) {
701
14.1M
    case 's':
702
14.1M
    case 'r':
703
14.1M
    case 'a':
704
14.1M
        if (PyLong_CheckExact(v) && arg->width == -1 && arg->prec == -1) {
705
            /* Fast path */
706
169
            if (_PyLong_FormatWriter(writer, v, 10, arg->flags & F_ALT) == -1)
707
0
                return -1;
708
169
            return 1;
709
169
        }
710
711
14.1M
        if (PyUnicode_CheckExact(v) && arg->ch == 's') {
712
8.97M
            *p_str = Py_NewRef(v);
713
8.97M
        }
714
5.14M
        else {
715
5.14M
            if (arg->ch == 's')
716
5.14M
                *p_str = PyObject_Str(v);
717
6.63k
            else if (arg->ch == 'r')
718
6.63k
                *p_str = PyObject_Repr(v);
719
0
            else
720
0
                *p_str = PyObject_ASCII(v);
721
5.14M
        }
722
14.1M
        break;
723
724
0
    case 'i':
725
2.45M
    case 'd':
726
2.45M
    case 'u':
727
2.53M
    case 'o':
728
2.53M
    case 'x':
729
7.68M
    case 'X':
730
7.68M
    {
731
7.68M
        int ret = mainformatlong(v, ctx, arg, p_str, writer);
732
7.68M
        if (ret != 0)
733
2.45M
            return ret;
734
5.22M
        arg->sign = 1;
735
5.22M
        break;
736
7.68M
    }
737
738
0
    case 'e':
739
0
    case 'E':
740
95
    case 'f':
741
95
    case 'F':
742
95
    case 'g':
743
95
    case 'G':
744
95
        if (arg->width == -1 && arg->prec == -1
745
0
            && !(arg->flags & (F_SIGN | F_BLANK)))
746
0
        {
747
            /* Fast path */
748
0
            if (formatfloat(v, ctx, arg, NULL, writer) == -1)
749
0
                return -1;
750
0
            return 1;
751
0
        }
752
753
95
        arg->sign = 1;
754
95
        if (formatfloat(v, ctx, arg, p_str, NULL) == -1)
755
0
            return -1;
756
95
        break;
757
758
95
    case 'c':
759
0
    {
760
0
        Py_UCS4 ch = formatchar(v, ctx, arg);
761
0
        if (ch == (Py_UCS4) -1)
762
0
            return -1;
763
0
        if (arg->width == -1 && arg->prec == -1) {
764
            /* Fast path */
765
0
            if (_PyUnicodeWriter_WriteCharInline(writer, ch) < 0)
766
0
                return -1;
767
0
            return 1;
768
0
        }
769
0
        *p_str = PyUnicode_FromOrdinal(ch);
770
0
        break;
771
0
    }
772
773
0
    default:
774
0
        if (arg->ch < 128 && Py_ISALPHA(arg->ch)) {
775
0
            PyErr_Format(PyExc_ValueError,
776
0
                         "unsupported format %%%c at position %zd",
777
0
                         (int)arg->ch, arg->fmtstart);
778
0
        }
779
0
        else if (arg->ch == '\'') {
780
0
            PyErr_Format(PyExc_ValueError,
781
0
                         "stray %% at position %zd or unexpected "
782
0
                         "format character \"'\" at position %zd",
783
0
                         arg->fmtstart,
784
0
                         ctx->fmtpos - 1);
785
0
        }
786
0
        else if (arg->ch >= 32 && arg->ch < 127) {
787
0
            PyErr_Format(PyExc_ValueError,
788
0
                         "stray %% at position %zd or unexpected "
789
0
                         "format character '%c' at position %zd",
790
0
                         arg->fmtstart,
791
0
                         (int)arg->ch, ctx->fmtpos - 1);
792
0
        }
793
0
        else if (Py_UNICODE_ISPRINTABLE(arg->ch)) {
794
0
            PyErr_Format(PyExc_ValueError,
795
0
                         "stray %% at position %zd or unexpected "
796
0
                         "format character '%c' (U+%04X) at position %zd",
797
0
                         arg->fmtstart,
798
0
                         (int)arg->ch, (int)arg->ch, ctx->fmtpos - 1);
799
0
        }
800
0
        else {
801
0
            PyErr_Format(PyExc_ValueError,
802
0
                         "stray %% at position %zd or unexpected "
803
0
                         "format character U+%04X at position %zd",
804
0
                         arg->fmtstart, (int)arg->ch, ctx->fmtpos - 1);
805
0
        }
806
0
        return -1;
807
21.8M
    }
808
19.3M
    if (*p_str == NULL)
809
0
        return -1;
810
19.3M
    assert (PyUnicode_Check(*p_str));
811
19.3M
    return 0;
812
19.3M
}
813
814
815
static int
816
unicode_format_arg_output(struct unicode_formatter_t *ctx,
817
                          struct unicode_format_arg_t *arg,
818
                          PyObject *str)
819
19.3M
{
820
19.3M
    Py_ssize_t len;
821
19.3M
    int kind;
822
19.3M
    const void *pbuf;
823
19.3M
    Py_ssize_t pindex;
824
19.3M
    Py_UCS4 signchar;
825
19.3M
    Py_ssize_t buflen;
826
19.3M
    Py_UCS4 maxchar;
827
19.3M
    Py_ssize_t sublen;
828
19.3M
    _PyUnicodeWriter *writer = &ctx->writer;
829
19.3M
    Py_UCS4 fill;
830
831
19.3M
    fill = ' ';
832
19.3M
    if (arg->sign && arg->flags & F_ZERO)
833
79.7k
        fill = '0';
834
835
19.3M
    len = PyUnicode_GET_LENGTH(str);
836
19.3M
    if ((arg->width == -1 || arg->width <= len)
837
19.2M
        && (arg->prec == -1 || arg->prec >= len)
838
19.2M
        && !(arg->flags & (F_SIGN | F_BLANK)))
839
19.2M
    {
840
        /* Fast path */
841
19.2M
        if (_PyUnicodeWriter_WriteStr(writer, str) == -1)
842
0
            return -1;
843
19.2M
        return 0;
844
19.2M
    }
845
846
    /* Truncate the string for "s", "r" and "a" formats
847
       if the precision is set */
848
77.8k
    if (arg->ch == 's' || arg->ch == 'r' || arg->ch == 'a') {
849
0
        if (arg->prec >= 0 && len > arg->prec)
850
0
            len = arg->prec;
851
0
    }
852
853
    /* Adjust sign and width */
854
77.8k
    kind = PyUnicode_KIND(str);
855
77.8k
    pbuf = PyUnicode_DATA(str);
856
77.8k
    pindex = 0;
857
77.8k
    signchar = '\0';
858
77.8k
    if (arg->sign) {
859
77.8k
        Py_UCS4 ch = PyUnicode_READ(kind, pbuf, pindex);
860
77.8k
        if (ch == '-' || ch == '+') {
861
0
            signchar = ch;
862
0
            len--;
863
0
            pindex++;
864
0
        }
865
77.8k
        else if (arg->flags & F_SIGN)
866
0
            signchar = '+';
867
77.8k
        else if (arg->flags & F_BLANK)
868
0
            signchar = ' ';
869
77.8k
        else
870
77.8k
            arg->sign = 0;
871
77.8k
    }
872
77.8k
    if (arg->width < len)
873
95
        arg->width = len;
874
875
    /* Prepare the writer */
876
77.8k
    maxchar = writer->maxchar;
877
77.8k
    if (!(arg->flags & F_LJUST)) {
878
77.8k
        if (arg->sign) {
879
0
            if ((arg->width-1) > len)
880
0
                maxchar = Py_MAX(maxchar, fill);
881
0
        }
882
77.8k
        else {
883
77.8k
            if (arg->width > len)
884
77.7k
                maxchar = Py_MAX(maxchar, fill);
885
77.8k
        }
886
77.8k
    }
887
77.8k
    if (PyUnicode_MAX_CHAR_VALUE(str) > maxchar) {
888
77.5k
        Py_UCS4 strmaxchar = _PyUnicode_FindMaxChar(str, 0, pindex+len);
889
77.5k
        maxchar = Py_MAX(maxchar, strmaxchar);
890
77.5k
    }
891
892
77.8k
    buflen = arg->width;
893
77.8k
    if (arg->sign && len == arg->width)
894
0
        buflen++;
895
77.8k
    if (_PyUnicodeWriter_Prepare(writer, buflen, maxchar) == -1)
896
0
        return -1;
897
898
    /* Write the sign if needed */
899
77.8k
    if (arg->sign) {
900
0
        if (fill != ' ') {
901
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar);
902
0
            writer->pos += 1;
903
0
        }
904
0
        if (arg->width > len)
905
0
            arg->width--;
906
0
    }
907
908
    /* Write the numeric prefix for "x", "X" and "o" formats
909
       if the alternate form is used.
910
       For example, write "0x" for the "%#x" format. */
911
77.8k
    if ((arg->flags & F_ALT) && (arg->ch == 'x' || arg->ch == 'X' || arg->ch == 'o')) {
912
0
        assert(PyUnicode_READ(kind, pbuf, pindex) == '0');
913
0
        assert(PyUnicode_READ(kind, pbuf, pindex + 1) == arg->ch);
914
0
        if (fill != ' ') {
915
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, '0');
916
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos+1, arg->ch);
917
0
            writer->pos += 2;
918
0
            pindex += 2;
919
0
        }
920
0
        arg->width -= 2;
921
0
        if (arg->width < 0)
922
0
            arg->width = 0;
923
0
        len -= 2;
924
0
    }
925
926
    /* Pad left with the fill character if needed */
927
77.8k
    if (arg->width > len && !(arg->flags & F_LJUST)) {
928
77.7k
        sublen = arg->width - len;
929
77.7k
        _PyUnicode_Fill(writer->kind, writer->data, fill, writer->pos, sublen);
930
77.7k
        writer->pos += sublen;
931
77.7k
        arg->width = len;
932
77.7k
    }
933
934
    /* If padding with spaces: write sign if needed and/or numeric prefix if
935
       the alternate form is used */
936
77.8k
    if (fill == ' ') {
937
95
        if (arg->sign) {
938
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar);
939
0
            writer->pos += 1;
940
0
        }
941
95
        if ((arg->flags & F_ALT) && (arg->ch == 'x' || arg->ch == 'X' || arg->ch == 'o')) {
942
0
            assert(PyUnicode_READ(kind, pbuf, pindex) == '0');
943
0
            assert(PyUnicode_READ(kind, pbuf, pindex+1) == arg->ch);
944
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, '0');
945
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos+1, arg->ch);
946
0
            writer->pos += 2;
947
0
            pindex += 2;
948
0
        }
949
95
    }
950
951
    /* Write characters */
952
77.8k
    if (len) {
953
77.8k
        _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
954
77.8k
                                      str, pindex, len);
955
77.8k
        writer->pos += len;
956
77.8k
    }
957
958
    /* Pad right with the fill character if needed */
959
77.8k
    if (arg->width > len) {
960
0
        sublen = arg->width - len;
961
0
        _PyUnicode_Fill(writer->kind, writer->data, ' ', writer->pos, sublen);
962
0
        writer->pos += sublen;
963
0
    }
964
77.8k
    return 0;
965
77.8k
}
966
967
968
/* Helper of PyUnicode_Format(): format one arg.
969
   Return 0 on success, raise an exception and return -1 on error. */
970
static int
971
unicode_format_arg(struct unicode_formatter_t *ctx)
972
21.8M
{
973
21.8M
    struct unicode_format_arg_t arg;
974
21.8M
    PyObject *str;
975
21.8M
    int ret;
976
977
21.8M
    arg.ch = PyUnicode_READ(ctx->fmtkind, ctx->fmtdata, ctx->fmtpos);
978
21.8M
    if (arg.ch == '%') {
979
0
        ctx->fmtpos++;
980
0
        ctx->fmtcnt--;
981
0
        if (_PyUnicodeWriter_WriteCharInline(&ctx->writer, '%') < 0)
982
0
            return -1;
983
0
        return 0;
984
0
    }
985
21.8M
    arg.flags = 0;
986
21.8M
    arg.width = -1;
987
21.8M
    arg.prec = -1;
988
21.8M
    arg.sign = 0;
989
21.8M
    arg.fmtstart = ctx->fmtpos - 1;
990
21.8M
    arg.key = NULL;
991
21.8M
    str = NULL;
992
993
21.8M
    ret = unicode_format_arg_parse(ctx, &arg);
994
21.8M
    if (ret == -1) {
995
0
        goto onError;
996
0
    }
997
998
21.8M
    ret = unicode_format_arg_format(ctx, &arg, &str);
999
21.8M
    if (ret == -1) {
1000
950k
        goto onError;
1001
950k
    }
1002
1003
20.8M
    if (ret != 1) {
1004
19.3M
        ret = unicode_format_arg_output(ctx, &arg, str);
1005
19.3M
        Py_DECREF(str);
1006
19.3M
        if (ret == -1) {
1007
0
            goto onError;
1008
0
        }
1009
19.3M
    }
1010
1011
20.8M
    if (ctx->dict && (ctx->argidx < ctx->arglen)) {
1012
        // XXX: Never happens?
1013
0
        PyErr_SetString(PyExc_TypeError,
1014
0
                        "not all arguments converted during string formatting");
1015
0
        goto onError;
1016
0
    }
1017
20.8M
    Py_XDECREF(arg.key);
1018
20.8M
    return 0;
1019
1020
950k
  onError:
1021
950k
    Py_XDECREF(arg.key);
1022
950k
    return -1;
1023
20.8M
}
1024
1025
1026
PyObject *
1027
PyUnicode_Format(PyObject *format, PyObject *args)
1028
12.1M
{
1029
12.1M
    struct unicode_formatter_t ctx;
1030
1031
12.1M
    if (format == NULL || args == NULL) {
1032
0
        PyErr_BadInternalCall();
1033
0
        return NULL;
1034
0
    }
1035
1036
12.1M
    if (ensure_unicode(format) < 0)
1037
0
        return NULL;
1038
1039
12.1M
    ctx.fmtstr = format;
1040
12.1M
    ctx.fmtdata = PyUnicode_DATA(ctx.fmtstr);
1041
12.1M
    ctx.fmtkind = PyUnicode_KIND(ctx.fmtstr);
1042
12.1M
    ctx.fmtcnt = PyUnicode_GET_LENGTH(ctx.fmtstr);
1043
12.1M
    ctx.fmtpos = 0;
1044
1045
12.1M
    _PyUnicodeWriter_Init(&ctx.writer);
1046
12.1M
    ctx.writer.min_length = ctx.fmtcnt + 100;
1047
12.1M
    ctx.writer.overallocate = 1;
1048
1049
12.1M
    if (PyTuple_Check(args)) {
1050
6.36M
        ctx.arglen = PyTuple_Size(args);
1051
6.36M
        ctx.argidx = 0;
1052
6.36M
    }
1053
5.80M
    else {
1054
5.80M
        ctx.arglen = -1;
1055
5.80M
        ctx.argidx = -2;
1056
5.80M
    }
1057
12.1M
    ctx.args_owned = 0;
1058
12.1M
    if (PyMapping_Check(args) && !PyTuple_Check(args) && !PyUnicode_Check(args))
1059
15.4k
        ctx.dict = args;
1060
12.1M
    else
1061
12.1M
        ctx.dict = NULL;
1062
12.1M
    ctx.args = args;
1063
1064
57.1M
    while (--ctx.fmtcnt >= 0) {
1065
45.8M
        if (PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') {
1066
24.0M
            Py_ssize_t nonfmtpos;
1067
1068
24.0M
            nonfmtpos = ctx.fmtpos++;
1069
142M
            while (ctx.fmtcnt >= 0 &&
1070
137M
                   PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') {
1071
118M
                ctx.fmtpos++;
1072
118M
                ctx.fmtcnt--;
1073
118M
            }
1074
24.0M
            if (ctx.fmtcnt < 0) {
1075
4.58M
                ctx.fmtpos--;
1076
4.58M
                ctx.writer.overallocate = 0;
1077
4.58M
            }
1078
1079
24.0M
            if (_PyUnicodeWriter_WriteSubstring(&ctx.writer, ctx.fmtstr,
1080
24.0M
                                                nonfmtpos, ctx.fmtpos) < 0)
1081
0
                goto onError;
1082
24.0M
        }
1083
21.8M
        else {
1084
21.8M
            ctx.fmtpos++;
1085
21.8M
            if (unicode_format_arg(&ctx) == -1)
1086
950k
                goto onError;
1087
21.8M
        }
1088
45.8M
    }
1089
1090
11.2M
    if (ctx.argidx < ctx.arglen && !ctx.dict) {
1091
0
        PyErr_Format(PyExc_TypeError,
1092
0
                     "not all arguments converted during string formatting "
1093
0
                     "(required %zd, got %zd)",
1094
0
                     ctx.arglen < 0 ? 0 : ctx.argidx,
1095
0
                     ctx.arglen < 0 ? 1 : ctx.arglen);
1096
0
        goto onError;
1097
0
    }
1098
1099
11.2M
    if (ctx.args_owned) {
1100
14.7k
        Py_DECREF(ctx.args);
1101
14.7k
    }
1102
11.2M
    return _PyUnicodeWriter_Finish(&ctx.writer);
1103
1104
950k
  onError:
1105
950k
    _PyUnicodeWriter_Dealloc(&ctx.writer);
1106
950k
    if (ctx.args_owned) {
1107
0
        Py_DECREF(ctx.args);
1108
0
    }
1109
    return NULL;
1110
11.2M
}