Coverage Report

Created: 2026-09-27 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/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
1.25M
#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
0
#define FORMAT_ERROR(EXC, FMT, ...) do {                                    \
82
0
    if (arg->key != NULL) {                                                 \
83
0
        PyErr_Format((EXC), "format argument %R: " FMT,                     \
84
0
                     arg->key, __VA_ARGS__);                                \
85
0
    }                                                                       \
86
0
    else if (ctx->argidx >= 0) {                                            \
87
0
        PyErr_Format((EXC), "format argument %zd: " FMT,                    \
88
0
                     ctx->argidx, __VA_ARGS__);                             \
89
0
    }                                                                       \
90
0
    else {                                                                  \
91
0
        PyErr_Format((EXC), "format argument: " FMT, __VA_ARGS__);          \
92
0
    }                                                                       \
93
0
} while (0)
94
95
96
static PyObject *
97
unicode_format_getnextarg(struct unicode_formatter_t *ctx, int allowone)
98
1.27M
{
99
1.27M
    Py_ssize_t argidx = ctx->argidx;
100
101
1.27M
    if (argidx < ctx->arglen && (allowone || ctx->arglen >= 0)) {
102
1.27M
        ctx->argidx++;
103
1.27M
        if (ctx->arglen >= 0) {
104
31.6k
            return PyTuple_GetItem(ctx->args, argidx);
105
31.6k
        }
106
1.24M
        else if (allowone) {
107
1.24M
            return ctx->args;
108
1.24M
        }
109
1.27M
    }
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
1.27M
}
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
0
{
130
0
    char *p;
131
0
    double x;
132
0
    Py_ssize_t len;
133
0
    int prec;
134
0
    int dtoa_flags = 0;
135
136
0
    x = PyFloat_AsDouble(v);
137
0
    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
0
    prec = arg->prec;
147
0
    if (prec < 0)
148
0
        prec = 6;
149
150
0
    if (arg->flags & F_ALT)
151
0
        dtoa_flags |= Py_DTSF_ALT;
152
0
    p = PyOS_double_to_string(x, arg->ch, prec, dtoa_flags, NULL);
153
0
    if (p == NULL)
154
0
        return -1;
155
0
    len = strlen(p);
156
0
    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
0
    else {
163
0
        *p_output = _PyUnicode_FromASCII(p, len);
164
0
        if (*p_output == NULL) {
165
0
            PyMem_Free(p);
166
0
            return -1;
167
0
        }
168
0
    }
169
0
    PyMem_Free(p);
170
0
    return 0;
171
0
}
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
0
{
195
0
    PyObject *result = NULL;
196
0
    char *buf;
197
0
    Py_ssize_t i;
198
0
    int sign;           /* 1 if '-', else 0 */
199
0
    int len;            /* number of characters */
200
0
    Py_ssize_t llen;
201
0
    int numdigits;      /* len == numnondigits + numdigits */
202
0
    int numnondigits = 0;
203
204
    /* Avoid exceeding SSIZE_T_MAX */
205
0
    if (prec > INT_MAX-3) {
206
0
        PyErr_SetString(PyExc_OverflowError,
207
0
                        "precision too large");
208
0
        return NULL;
209
0
    }
210
211
0
    assert(PyLong_Check(val));
212
213
0
    switch (type) {
214
0
    default:
215
0
        Py_UNREACHABLE();
216
0
    case 'd':
217
0
    case 'i':
218
0
    case 'u':
219
        /* int and int subclasses should print numerically when a numeric */
220
        /* format code is used (see issue18780) */
221
0
        result = PyNumber_ToBase(val, 10);
222
0
        break;
223
0
    case 'o':
224
0
        numnondigits = 2;
225
0
        result = PyNumber_ToBase(val, 8);
226
0
        break;
227
0
    case 'x':
228
0
    case 'X':
229
0
        numnondigits = 2;
230
0
        result = PyNumber_ToBase(val, 16);
231
0
        break;
232
0
    }
233
0
    if (!result)
234
0
        return NULL;
235
236
0
    assert(_PyUnicode_IsModifiable(result));
237
0
    assert(PyUnicode_IS_ASCII(result));
238
239
    /* To modify the string in-place, there can only be one reference. */
240
0
    if (!_PyObject_IsUniquelyReferenced(result)) {
241
0
        Py_DECREF(result);
242
0
        PyErr_BadInternalCall();
243
0
        return NULL;
244
0
    }
245
0
    buf = PyUnicode_DATA(result);
246
0
    llen = PyUnicode_GET_LENGTH(result);
247
0
    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
0
    len = (int)llen;
254
0
    sign = buf[0] == '-';
255
0
    numnondigits += sign;
256
0
    numdigits = len - numnondigits;
257
0
    assert(numdigits > 0);
258
259
    /* Get rid of base marker unless F_ALT */
260
0
    if (((alt) == 0 &&
261
0
        (type == 'o' || type == 'x' || type == 'X'))) {
262
0
        assert(buf[sign] == '0');
263
0
        assert(buf[sign+1] == 'x' || buf[sign+1] == 'X' ||
264
0
               buf[sign+1] == 'o');
265
0
        numnondigits -= 2;
266
0
        buf += 2;
267
0
        len -= 2;
268
0
        if (sign)
269
0
            buf[0] = '-';
270
0
        assert(len == numnondigits + numdigits);
271
0
        assert(numdigits > 0);
272
0
    }
273
274
    /* Fill with leading zeroes to meet minimum width. */
275
0
    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
0
    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
0
        for (i = 0; i < len; i++)
301
0
            if (buf[i] >= 'a' && buf[i] <= 'x')
302
0
                buf[i] -= 'a'-'A';
303
0
    }
304
0
    if (!PyUnicode_Check(result)
305
0
        || buf != PyUnicode_DATA(result)) {
306
0
        PyObject *unicode;
307
0
        unicode = _PyUnicode_FromASCII(buf, len);
308
0
        Py_SETREF(result, unicode);
309
0
    }
310
0
    else if (len != PyUnicode_GET_LENGTH(result)) {
311
0
        if (PyUnicode_Resize(&result, len) < 0)
312
0
            Py_CLEAR(result);
313
0
    }
314
0
    return result;
315
0
}
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
1.26M
{
329
1.26M
    PyObject *iobj, *res;
330
1.26M
    char type = (char)arg->ch;
331
332
1.26M
    if (!PyNumber_Check(v))
333
0
        goto wrongtype;
334
335
    /* make sure number is a type of integer for o, x, and X */
336
1.26M
    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
1.26M
    else {
351
1.26M
        iobj = Py_NewRef(v);
352
1.26M
    }
353
354
1.26M
    if (PyLong_CheckExact(v)
355
1.26M
        && arg->width == -1 && arg->prec == -1
356
1.26M
        && !(arg->flags & (F_SIGN | F_BLANK))
357
1.26M
        && type != 'X')
358
1.26M
    {
359
        /* Fast path */
360
1.26M
        int alternate = arg->flags & F_ALT;
361
1.26M
        int base;
362
363
1.26M
        switch(type)
364
1.26M
        {
365
0
            default:
366
0
                Py_UNREACHABLE();
367
1.26M
            case 'd':
368
1.26M
            case 'i':
369
1.26M
            case 'u':
370
1.26M
                base = 10;
371
1.26M
                break;
372
0
            case 'o':
373
0
                base = 8;
374
0
                break;
375
0
            case 'x':
376
0
            case 'X':
377
0
                base = 16;
378
0
                break;
379
1.26M
        }
380
381
1.26M
        if (_PyLong_FormatWriter(writer, v, base, alternate) == -1) {
382
0
            Py_DECREF(iobj);
383
0
            return -1;
384
0
        }
385
1.26M
        Py_DECREF(iobj);
386
1.26M
        return 1;
387
1.26M
    }
388
389
0
    res = _PyUnicode_FormatLong(iobj, arg->flags & F_ALT, arg->prec, type);
390
0
    Py_DECREF(iobj);
391
0
    if (res == NULL)
392
0
        return -1;
393
0
    *p_output = res;
394
0
    return 0;
395
396
0
wrongtype:
397
0
    switch(type)
398
0
    {
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
0
        default:
407
0
            FORMAT_ERROR(PyExc_TypeError,
408
0
                         "%%%c requires a real number, not %T",
409
0
                         arg->ch, v);
410
0
            break;
411
0
    }
412
0
    return -1;
413
0
}
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
1.27M
{
467
1.27M
#define FORMAT_READ(ctx) \
468
1.27M
        PyUnicode_READ((ctx)->fmtkind, (ctx)->fmtdata, (ctx)->fmtpos)
469
470
1.27M
    PyObject *v;
471
472
1.27M
    if (arg->ch == '(') {
473
        /* Get argument value from a dictionary. Example: "%(name)s". */
474
0
        Py_ssize_t keystart;
475
0
        Py_ssize_t keylen;
476
0
        int pcount = 1;
477
478
0
        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
0
        ++ctx->fmtpos;
485
0
        --ctx->fmtcnt;
486
0
        keystart = ctx->fmtpos;
487
        /* Skip over balanced parentheses */
488
0
        while (pcount > 0 && --ctx->fmtcnt >= 0) {
489
0
            arg->ch = FORMAT_READ(ctx);
490
0
            if (arg->ch == ')')
491
0
                --pcount;
492
0
            else if (arg->ch == '(')
493
0
                ++pcount;
494
0
            ctx->fmtpos++;
495
0
        }
496
0
        keylen = ctx->fmtpos - keystart - 1;
497
0
        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
0
        arg->key = PyUnicode_Substring(ctx->fmtstr,
504
0
                                       keystart, keystart + keylen);
505
0
        if (arg->key == NULL)
506
0
            return -1;
507
0
        if (ctx->args_owned) {
508
0
            ctx->args_owned = 0;
509
0
            Py_DECREF(ctx->args);
510
0
        }
511
0
        ctx->args = PyObject_GetItem(ctx->dict, arg->key);
512
0
        if (ctx->args == NULL)
513
0
            return -1;
514
0
        ctx->args_owned = 1;
515
0
        ctx->arglen = -3;
516
0
        ctx->argidx = -4;
517
0
    }
518
1.27M
    else {
519
1.27M
        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
1.27M
    }
527
528
    /* Parse flags. Example: "%+i" => flags=F_SIGN. */
529
1.27M
    while (--ctx->fmtcnt >= 0) {
530
1.27M
        arg->ch = FORMAT_READ(ctx);
531
1.27M
        ctx->fmtpos++;
532
1.27M
        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
0
        case '#': arg->flags |= F_ALT; continue;
537
0
        case '0': arg->flags |= F_ZERO; continue;
538
1.27M
        }
539
1.27M
        break;
540
1.27M
    }
541
542
    /* Parse width. Example: "%10s" => width=10 */
543
1.27M
    if (arg->ch == '*') {
544
0
        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
0
        v = unicode_format_getnextarg(ctx, 0);
552
0
        if (v == NULL)
553
0
            return -1;
554
0
        if (!PyLong_Check(v)) {
555
0
            FORMAT_ERROR(PyExc_TypeError, "* requires int, not %T", v);
556
0
            return -1;
557
0
        }
558
0
        arg->width = PyLong_AsSsize_t(v);
559
0
        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
0
        if (arg->width < 0) {
567
0
            arg->flags |= F_LJUST;
568
0
            arg->width = -arg->width;
569
0
        }
570
0
        if (--ctx->fmtcnt >= 0) {
571
0
            arg->ch = FORMAT_READ(ctx);
572
0
            ctx->fmtpos++;
573
0
        }
574
0
    }
575
1.27M
    else if (arg->ch >= '0' && arg->ch <= '9') {
576
0
        arg->width = arg->ch - '0';
577
0
        while (--ctx->fmtcnt >= 0) {
578
0
            arg->ch = FORMAT_READ(ctx);
579
0
            ctx->fmtpos++;
580
0
            if (arg->ch < '0' || arg->ch > '9')
581
0
                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
0
    }
594
595
    /* Parse precision. Example: "%.3f" => prec=3 */
596
1.27M
    if (arg->ch == '.') {
597
0
        arg->prec = 0;
598
0
        if (--ctx->fmtcnt >= 0) {
599
0
            arg->ch = FORMAT_READ(ctx);
600
0
            ctx->fmtpos++;
601
0
        }
602
0
        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
0
        else if (arg->ch >= '0' && arg->ch <= '9') {
633
0
            arg->prec = arg->ch - '0';
634
0
            while (--ctx->fmtcnt >= 0) {
635
0
                arg->ch = FORMAT_READ(ctx);
636
0
                ctx->fmtpos++;
637
0
                if (arg->ch < '0' || arg->ch > '9')
638
0
                    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
0
        }
648
0
    }
649
650
    /* Ignore "h", "l" and "L" format prefix (ex: "%hi" or "%ls") */
651
1.27M
    if (ctx->fmtcnt >= 0) {
652
1.27M
        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
1.27M
    }
659
1.27M
    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
1.27M
    return 0;
665
666
1.27M
#undef FORMAT_READ
667
1.27M
}
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
1.27M
{
689
1.27M
    PyObject *v;
690
1.27M
    _PyUnicodeWriter *writer = &ctx->writer;
691
692
1.27M
    if (ctx->fmtcnt == 0)
693
1.24M
        ctx->writer.overallocate = 0;
694
695
1.27M
    v = unicode_format_getnextarg(ctx, 1);
696
1.27M
    if (v == NULL)
697
0
        return -1;
698
699
700
1.27M
    switch (arg->ch) {
701
9.20k
    case 's':
702
9.34k
    case 'r':
703
9.59k
    case 'a':
704
9.59k
        if (PyLong_CheckExact(v) && arg->width == -1 && arg->prec == -1) {
705
            /* Fast path */
706
0
            if (_PyLong_FormatWriter(writer, v, 10, arg->flags & F_ALT) == -1)
707
0
                return -1;
708
0
            return 1;
709
0
        }
710
711
9.59k
        if (PyUnicode_CheckExact(v) && arg->ch == 's') {
712
9.20k
            *p_str = Py_NewRef(v);
713
9.20k
        }
714
383
        else {
715
383
            if (arg->ch == 's')
716
0
                *p_str = PyObject_Str(v);
717
383
            else if (arg->ch == 'r')
718
134
                *p_str = PyObject_Repr(v);
719
249
            else
720
249
                *p_str = PyObject_ASCII(v);
721
383
        }
722
9.59k
        break;
723
724
0
    case 'i':
725
1.26M
    case 'd':
726
1.26M
    case 'u':
727
1.26M
    case 'o':
728
1.26M
    case 'x':
729
1.26M
    case 'X':
730
1.26M
    {
731
1.26M
        int ret = mainformatlong(v, ctx, arg, p_str, writer);
732
1.26M
        if (ret != 0)
733
1.26M
            return ret;
734
0
        arg->sign = 1;
735
0
        break;
736
1.26M
    }
737
738
0
    case 'e':
739
0
    case 'E':
740
0
    case 'f':
741
0
    case 'F':
742
0
    case 'g':
743
0
    case 'G':
744
0
        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
0
        arg->sign = 1;
754
0
        if (formatfloat(v, ctx, arg, p_str, NULL) == -1)
755
0
            return -1;
756
0
        break;
757
758
0
    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
1.27M
    }
808
9.59k
    if (*p_str == NULL)
809
0
        return -1;
810
9.59k
    assert (PyUnicode_Check(*p_str));
811
9.59k
    return 0;
812
9.59k
}
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
9.59k
{
820
9.59k
    Py_ssize_t len;
821
9.59k
    int kind;
822
9.59k
    const void *pbuf;
823
9.59k
    Py_ssize_t pindex;
824
9.59k
    Py_UCS4 signchar;
825
9.59k
    Py_ssize_t buflen;
826
9.59k
    Py_UCS4 maxchar;
827
9.59k
    Py_ssize_t sublen;
828
9.59k
    _PyUnicodeWriter *writer = &ctx->writer;
829
9.59k
    Py_UCS4 fill;
830
831
9.59k
    fill = ' ';
832
9.59k
    if (arg->sign && arg->flags & F_ZERO)
833
0
        fill = '0';
834
835
9.59k
    len = PyUnicode_GET_LENGTH(str);
836
9.59k
    if ((arg->width == -1 || arg->width <= len)
837
9.59k
        && (arg->prec == -1 || arg->prec >= len)
838
9.59k
        && !(arg->flags & (F_SIGN | F_BLANK)))
839
9.59k
    {
840
        /* Fast path */
841
9.59k
        if (_PyUnicodeWriter_WriteStr(writer, str) == -1)
842
0
            return -1;
843
9.59k
        return 0;
844
9.59k
    }
845
846
    /* Truncate the string for "s", "r" and "a" formats
847
       if the precision is set */
848
0
    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
0
    kind = PyUnicode_KIND(str);
855
0
    pbuf = PyUnicode_DATA(str);
856
0
    pindex = 0;
857
0
    signchar = '\0';
858
0
    if (arg->sign) {
859
0
        Py_UCS4 ch = PyUnicode_READ(kind, pbuf, pindex);
860
0
        if (ch == '-' || ch == '+') {
861
0
            signchar = ch;
862
0
            len--;
863
0
            pindex++;
864
0
        }
865
0
        else if (arg->flags & F_SIGN)
866
0
            signchar = '+';
867
0
        else if (arg->flags & F_BLANK)
868
0
            signchar = ' ';
869
0
        else
870
0
            arg->sign = 0;
871
0
    }
872
0
    if (arg->width < len)
873
0
        arg->width = len;
874
875
    /* Prepare the writer */
876
0
    maxchar = writer->maxchar;
877
0
    if (!(arg->flags & F_LJUST)) {
878
0
        if (arg->sign) {
879
0
            if ((arg->width-1) > len)
880
0
                maxchar = Py_MAX(maxchar, fill);
881
0
        }
882
0
        else {
883
0
            if (arg->width > len)
884
0
                maxchar = Py_MAX(maxchar, fill);
885
0
        }
886
0
    }
887
0
    if (PyUnicode_MAX_CHAR_VALUE(str) > maxchar) {
888
0
        Py_UCS4 strmaxchar = _PyUnicode_FindMaxChar(str, 0, pindex+len);
889
0
        maxchar = Py_MAX(maxchar, strmaxchar);
890
0
    }
891
892
0
    buflen = arg->width;
893
0
    if (arg->sign && len == arg->width)
894
0
        buflen++;
895
0
    if (_PyUnicodeWriter_Prepare(writer, buflen, maxchar) == -1)
896
0
        return -1;
897
898
    /* Write the sign if needed */
899
0
    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
0
    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
0
    if (arg->width > len && !(arg->flags & F_LJUST)) {
928
0
        sublen = arg->width - len;
929
0
        _PyUnicode_Fill(writer->kind, writer->data, fill, writer->pos, sublen);
930
0
        writer->pos += sublen;
931
0
        arg->width = len;
932
0
    }
933
934
    /* If padding with spaces: write sign if needed and/or numeric prefix if
935
       the alternate form is used */
936
0
    if (fill == ' ') {
937
0
        if (arg->sign) {
938
0
            PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar);
939
0
            writer->pos += 1;
940
0
        }
941
0
        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
0
    }
950
951
    /* Write characters */
952
0
    if (len) {
953
0
        _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
954
0
                                      str, pindex, len);
955
0
        writer->pos += len;
956
0
    }
957
958
    /* Pad right with the fill character if needed */
959
0
    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
0
    return 0;
965
0
}
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
1.27M
{
973
1.27M
    struct unicode_format_arg_t arg;
974
1.27M
    PyObject *str;
975
1.27M
    int ret;
976
977
1.27M
    arg.ch = PyUnicode_READ(ctx->fmtkind, ctx->fmtdata, ctx->fmtpos);
978
1.27M
    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
1.27M
    arg.flags = 0;
986
1.27M
    arg.width = -1;
987
1.27M
    arg.prec = -1;
988
1.27M
    arg.sign = 0;
989
1.27M
    arg.fmtstart = ctx->fmtpos - 1;
990
1.27M
    arg.key = NULL;
991
1.27M
    str = NULL;
992
993
1.27M
    ret = unicode_format_arg_parse(ctx, &arg);
994
1.27M
    if (ret == -1) {
995
0
        goto onError;
996
0
    }
997
998
1.27M
    ret = unicode_format_arg_format(ctx, &arg, &str);
999
1.27M
    if (ret == -1) {
1000
0
        goto onError;
1001
0
    }
1002
1003
1.27M
    if (ret != 1) {
1004
9.59k
        ret = unicode_format_arg_output(ctx, &arg, str);
1005
9.59k
        Py_DECREF(str);
1006
9.59k
        if (ret == -1) {
1007
0
            goto onError;
1008
0
        }
1009
9.59k
    }
1010
1011
1.27M
    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
1.27M
    Py_XDECREF(arg.key);
1018
1.27M
    return 0;
1019
1020
0
  onError:
1021
0
    Py_XDECREF(arg.key);
1022
0
    return -1;
1023
1.27M
}
1024
1025
1026
PyObject *
1027
PyUnicode_Format(PyObject *format, PyObject *args)
1028
1.25M
{
1029
1.25M
    struct unicode_formatter_t ctx;
1030
1031
1.25M
    if (format == NULL || args == NULL) {
1032
0
        PyErr_BadInternalCall();
1033
0
        return NULL;
1034
0
    }
1035
1036
1.25M
    if (ensure_unicode(format) < 0)
1037
0
        return NULL;
1038
1039
1.25M
    ctx.fmtstr = format;
1040
1.25M
    ctx.fmtdata = PyUnicode_DATA(ctx.fmtstr);
1041
1.25M
    ctx.fmtkind = PyUnicode_KIND(ctx.fmtstr);
1042
1.25M
    ctx.fmtcnt = PyUnicode_GET_LENGTH(ctx.fmtstr);
1043
1.25M
    ctx.fmtpos = 0;
1044
1045
1.25M
    _PyUnicodeWriter_Init(&ctx.writer);
1046
1.25M
    ctx.writer.min_length = ctx.fmtcnt + 100;
1047
1.25M
    ctx.writer.overallocate = 1;
1048
1049
1.25M
    if (PyTuple_Check(args)) {
1050
9.04k
        ctx.arglen = PyTuple_Size(args);
1051
9.04k
        ctx.argidx = 0;
1052
9.04k
    }
1053
1.24M
    else {
1054
1.24M
        ctx.arglen = -1;
1055
1.24M
        ctx.argidx = -2;
1056
1.24M
    }
1057
1.25M
    ctx.args_owned = 0;
1058
1.25M
    if (PyMapping_Check(args) && !PyTuple_Check(args) && !PyUnicode_Check(args))
1059
0
        ctx.dict = args;
1060
1.25M
    else
1061
1.25M
        ctx.dict = NULL;
1062
1.25M
    ctx.args = args;
1063
1064
3.80M
    while (--ctx.fmtcnt >= 0) {
1065
2.55M
        if (PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') {
1066
1.27M
            Py_ssize_t nonfmtpos;
1067
1068
1.27M
            nonfmtpos = ctx.fmtpos++;
1069
55.3M
            while (ctx.fmtcnt >= 0 &&
1070
55.3M
                   PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') {
1071
54.0M
                ctx.fmtpos++;
1072
54.0M
                ctx.fmtcnt--;
1073
54.0M
            }
1074
1.27M
            if (ctx.fmtcnt < 0) {
1075
7.05k
                ctx.fmtpos--;
1076
7.05k
                ctx.writer.overallocate = 0;
1077
7.05k
            }
1078
1079
1.27M
            if (_PyUnicodeWriter_WriteSubstring(&ctx.writer, ctx.fmtstr,
1080
1.27M
                                                nonfmtpos, ctx.fmtpos) < 0)
1081
0
                goto onError;
1082
1.27M
        }
1083
1.27M
        else {
1084
1.27M
            ctx.fmtpos++;
1085
1.27M
            if (unicode_format_arg(&ctx) == -1)
1086
0
                goto onError;
1087
1.27M
        }
1088
2.55M
    }
1089
1090
1.25M
    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
1.25M
    if (ctx.args_owned) {
1100
0
        Py_DECREF(ctx.args);
1101
0
    }
1102
1.25M
    return _PyUnicodeWriter_Finish(&ctx.writer);
1103
1104
0
  onError:
1105
0
    _PyUnicodeWriter_Dealloc(&ctx.writer);
1106
0
    if (ctx.args_owned) {
1107
0
        Py_DECREF(ctx.args);
1108
0
    }
1109
    return NULL;
1110
1.25M
}