Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Parser/lexer/buffer.c
Line
Count
Source (jump to first uncovered line)
1
#include "Python.h"
2
#include "errcode.h"
3
4
#include "state.h"
5
6
/* Traverse and remember all f-string buffers, in order to be able to restore
7
   them after reallocating tok->buf */
8
void
9
_PyLexer_remember_fstring_buffers(struct tok_state *tok)
10
0
{
11
0
    int index;
12
0
    tokenizer_mode *mode;
13
14
0
    for (index = tok->tok_mode_stack_index; index >= 0; --index) {
15
0
        mode = &(tok->tok_mode_stack[index]);
16
0
        mode->start_offset = mode->start - tok->buf;
17
0
        mode->multi_line_start_offset = mode->multi_line_start - tok->buf;
18
0
    }
19
0
}
20
21
/* Traverse and restore all f-string buffers after reallocating tok->buf */
22
void
23
_PyLexer_restore_fstring_buffers(struct tok_state *tok)
24
0
{
25
0
    int index;
26
0
    tokenizer_mode *mode;
27
28
0
    for (index = tok->tok_mode_stack_index; index >= 0; --index) {
29
0
        mode = &(tok->tok_mode_stack[index]);
30
0
        mode->start = tok->buf + mode->start_offset;
31
0
        mode->multi_line_start = tok->buf + mode->multi_line_start_offset;
32
0
    }
33
0
}
34
35
/* Read a line of text from TOK into S, using the stream in TOK.
36
   Return NULL on failure, else S.
37
38
   On entry, tok->decoding_buffer will be one of:
39
     1) NULL: need to call tok->decoding_readline to get a new line
40
     2) PyUnicodeObject *: decoding_feof has called tok->decoding_readline and
41
       stored the result in tok->decoding_buffer
42
     3) PyByteArrayObject *: previous call to tok_readline_recode did not have enough room
43
       (in the s buffer) to copy entire contents of the line read
44
       by tok->decoding_readline.  tok->decoding_buffer has the overflow.
45
       In this case, tok_readline_recode is called in a loop (with an expanded buffer)
46
       until the buffer ends with a '\n' (or until the end of the file is
47
       reached): see tok_nextc and its calls to tok_reserve_buf.
48
*/
49
int
50
_PyLexer_tok_reserve_buf(struct tok_state *tok, Py_ssize_t size)
51
0
{
52
0
    Py_ssize_t cur = tok->cur - tok->buf;
53
0
    Py_ssize_t oldsize = tok->inp - tok->buf;
54
0
    Py_ssize_t newsize = oldsize + Py_MAX(size, oldsize >> 1);
55
0
    if (newsize > tok->end - tok->buf) {
56
0
        char *newbuf = tok->buf;
57
0
        Py_ssize_t start = tok->start == NULL ? -1 : tok->start - tok->buf;
58
0
        Py_ssize_t line_start = tok->start == NULL ? -1 : tok->line_start - tok->buf;
59
0
        Py_ssize_t multi_line_start = tok->multi_line_start - tok->buf;
60
0
        _PyLexer_remember_fstring_buffers(tok);
61
0
        newbuf = (char *)PyMem_Realloc(newbuf, newsize);
62
0
        if (newbuf == NULL) {
63
0
            tok->done = E_NOMEM;
64
0
            return 0;
65
0
        }
66
0
        tok->buf = newbuf;
67
0
        tok->cur = tok->buf + cur;
68
0
        tok->inp = tok->buf + oldsize;
69
0
        tok->end = tok->buf + newsize;
70
0
        tok->start = start < 0 ? NULL : tok->buf + start;
71
0
        tok->line_start = line_start < 0 ? NULL : tok->buf + line_start;
72
0
        tok->multi_line_start = multi_line_start < 0 ? NULL : tok->buf + multi_line_start;
73
0
        _PyLexer_restore_fstring_buffers(tok);
74
0
    }
75
0
    return 1;
76
0
}