Fix possibly-unitialized warning in string_parser.c. (GH-21503)

GCC says
```
../cpython/Parser/string_parser.c: In function ‘fstring_find_expr’:
../cpython/Parser/string_parser.c:404:93: warning: ‘cols’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  404 |     p2->starting_col_offset = p->tok->first_lineno == p->tok->lineno ? t->col_offset + cols : cols;
      |                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
../cpython/Parser/string_parser.c:384:16: note: ‘cols’ was declared here
  384 |     int lines, cols;
      |                ^~~~
../cpython/Parser/string_parser.c:403:45: warning: ‘lines’ may be used uninitialized in this function [-Wmaybe-uninitialized]
  403 |     p2->starting_lineno = t->lineno + lines - 1;
      |                           ~~~~~~~~~~~~~~~~~~^~~
../cpython/Parser/string_parser.c:384:9: note: ‘lines’ was declared here
  384 |     int lines, cols;
      |         ^~~~~
```

and, indeed, if `PyBytes_AsString` somehow fails, lines & cols will not be initialized.
This commit is contained in:
Benjamin Peterson 2020-07-16 06:07:29 -07:00 committed by GitHub
parent 5e5c0f9866
commit 2ad7e9c011
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 16 additions and 15 deletions

View File

@ -1,3 +1,5 @@
#include <stdbool.h>
#include <Python.h>
#include "tokenizer.h"
@ -277,26 +279,23 @@ _PyPegen_parsestr(Parser *p, int *bytesmode, int *rawmode, PyObject **result,
`n` is the node which locations are going to be fixed relative to parent.
`expr_str` is the child node's string representation, including braces.
*/
static void
static bool
fstring_find_expr_location(Token *parent, char *expr_str, int *p_lines, int *p_cols)
{
char *substr = NULL;
char *start;
int lines = 0;
int cols = 0;
*p_lines = 0;
*p_cols = 0;
if (parent && parent->bytes) {
char *parent_str = PyBytes_AsString(parent->bytes);
if (!parent_str) {
return;
return false;
}
substr = strstr(parent_str, expr_str);
char *substr = strstr(parent_str, expr_str);
if (substr) {
// The following is needed, in order to correctly shift the column
// offset, in the case that (disregarding any whitespace) a newline
// immediately follows the opening curly brace of the fstring expression.
int newline_after_brace = 1;
start = substr + 1;
bool newline_after_brace = 1;
char *start = substr + 1;
while (start && *start != '}' && *start != '\n') {
if (*start != ' ' && *start != '\t' && *start != '\f') {
newline_after_brace = 0;
@ -312,19 +311,18 @@ fstring_find_expr_location(Token *parent, char *expr_str, int *p_lines, int *p_c
while (start > parent_str && *start != '\n') {
start--;
}
cols += (int)(substr - start);
*p_cols += (int)(substr - start);
}
/* adjust the start based on the number of newlines encountered
before the f-string expression */
for (char* p = parent_str; p < substr; p++) {
if (*p == '\n') {
lines++;
(*p_lines)++;
}
}
}
}
*p_lines = lines;
*p_cols = cols;
return true;
}
@ -382,7 +380,10 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
str[len+2] = 0;
int lines, cols;
fstring_find_expr_location(t, str, &lines, &cols);
if (!fstring_find_expr_location(t, str, &lines, &cols)) {
PyMem_FREE(str);
return NULL;
}
// The parentheses are needed in order to allow for leading whitespace withing
// the f-string expression. This consequently gets parsed as a group (see the