Coverage Report

Created: 2026-10-17 06:15

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