@@ -72,20 +72,11 @@ chunk_set_unicode(struct tok_state *tok, _PyTok_Chunk *chunk,
7272 return 0 ;
7373}
7474
75- char *
76- _PyTok_NormalizeNewlines ( const char * data , Py_ssize_t len , int preserve_crlf ,
77- int add_final_newline , Py_ssize_t * out_len ,
78- int * implicit_newline )
75+ static void
76+ normalize_newlines_into ( char * result , const char * data , Py_ssize_t len ,
77+ int preserve_crlf , int add_final_newline ,
78+ Py_ssize_t * out_len , int * implicit_newline )
7979{
80- if (len > PY_SSIZE_T_MAX - 2 ) {
81- PyErr_NoMemory ();
82- return NULL ;
83- }
84- char * result = PyMem_Malloc ((size_t )len + 2 );
85- if (result == NULL ) {
86- PyErr_NoMemory ();
87- return NULL ;
88- }
8980 Py_ssize_t write = 0 ;
9081 for (Py_ssize_t read = 0 ; read < len ; read ++ ) {
9182 char c = data [read ];
@@ -104,6 +95,24 @@ _PyTok_NormalizeNewlines(const char *data, Py_ssize_t len, int preserve_crlf,
10495 result [write ] = '\0' ;
10596 * out_len = write ;
10697 * implicit_newline = implicit ;
98+ }
99+
100+ char *
101+ _PyTok_NormalizeNewlines (const char * data , Py_ssize_t len , int preserve_crlf ,
102+ int add_final_newline , Py_ssize_t * out_len ,
103+ int * implicit_newline )
104+ {
105+ if (len > PY_SSIZE_T_MAX - 2 ) {
106+ PyErr_NoMemory ();
107+ return NULL ;
108+ }
109+ char * result = PyMem_Malloc ((size_t )len + 2 );
110+ if (result == NULL ) {
111+ PyErr_NoMemory ();
112+ return NULL ;
113+ }
114+ normalize_newlines_into (result , data , len , preserve_crlf ,
115+ add_final_newline , out_len , implicit_newline );
107116 return result ;
108117}
109118
@@ -289,6 +298,8 @@ store_prepared_source(struct tok_state *tok, const char *data, Py_ssize_t len,
289298 int preserve_crlf , int add_final_newline )
290299{
291300 Py_ssize_t pos = 0 ;
301+ char * normalized = NULL ;
302+ Py_ssize_t capacity = 0 ;
292303 while (pos < len ) {
293304 Py_ssize_t raw_line_len ;
294305 if (preserve_crlf ) {
@@ -311,29 +322,51 @@ store_prepared_source(struct tok_state *tok, const char *data, Py_ssize_t len,
311322
312323 const char * line = data + pos ;
313324 Py_ssize_t line_len = raw_line_len ;
314- char * normalized = NULL ;
315325 int implicit = 0 ;
316326 if (normalize ) {
317- normalized = _PyTok_NormalizeNewlines (
318- line , line_len , preserve_crlf , add_newline ,
319- & line_len , & implicit );
320- if (normalized == NULL ) {
327+ if (line_len > PY_SSIZE_T_MAX - 2 ) {
328+ PyErr_NoMemory ();
321329 tok -> done = E_NOMEM ;
322- return -1 ;
330+ goto error ;
323331 }
332+ Py_ssize_t needed = line_len + 2 ;
333+ if (needed > capacity ) {
334+ Py_ssize_t next_capacity = capacity > 0 ? capacity : 256 ;
335+ while (next_capacity < needed ) {
336+ if (next_capacity > PY_SSIZE_T_MAX / 2 ) {
337+ next_capacity = needed ;
338+ break ;
339+ }
340+ next_capacity *= 2 ;
341+ }
342+ char * resized = PyMem_Realloc (normalized , next_capacity );
343+ if (resized == NULL ) {
344+ PyErr_NoMemory ();
345+ tok -> done = E_NOMEM ;
346+ goto error ;
347+ }
348+ normalized = resized ;
349+ capacity = next_capacity ;
350+ }
351+ normalize_newlines_into (normalized , line , line_len ,
352+ preserve_crlf , add_newline ,
353+ & line_len , & implicit );
324354 line = normalized ;
325355 }
326356 _PyTok_Off appended = _PyTok_SourceAppendLine (
327357 & tok -> source , line , line_len , implicit );
328- PyMem_Free (normalized );
329358 if (appended < 0 ) {
330359 tok -> done = PyErr_ExceptionMatches (PyExc_MemoryError )
331360 ? E_NOMEM : E_ERROR ;
332- return -1 ;
361+ goto error ;
333362 }
334363 pos += raw_line_len ;
335364 }
365+ PyMem_Free (normalized );
336366 return 0 ;
367+ error :
368+ PyMem_Free (normalized );
369+ return -1 ;
337370}
338371
339372int
0 commit comments