bpo-40958: Avoid buffer overflow in the parser when indexing the current line (GH-20875)

This commit is contained in:
Pablo Galindo 2020-06-16 16:49:43 +01:00 committed by GitHub
parent fcc60e40bb
commit 51c5896b62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 13 additions and 13 deletions

View File

@ -0,0 +1,2 @@
Fix a possible buffer overflow in the PEG parser when gathering information
for emitting syntax errors. Patch by Pablo Galindo.

View File

@ -140,21 +140,18 @@ _create_dummy_identifier(Parser *p)
} }
static inline Py_ssize_t static inline Py_ssize_t
byte_offset_to_character_offset(PyObject *line, int col_offset) byte_offset_to_character_offset(PyObject *line, Py_ssize_t col_offset)
{ {
const char *str = PyUnicode_AsUTF8(line); const char *str = PyUnicode_AsUTF8(line);
if (!str) { if (!str) {
return 0; return 0;
} }
assert(col_offset >= 0 && (unsigned long)col_offset <= strlen(str));
PyObject *text = PyUnicode_DecodeUTF8(str, col_offset, "replace"); PyObject *text = PyUnicode_DecodeUTF8(str, col_offset, "replace");
if (!text) { if (!text) {
return 0; return 0;
} }
Py_ssize_t size = PyUnicode_GET_LENGTH(text); Py_ssize_t size = PyUnicode_GET_LENGTH(text);
str = PyUnicode_AsUTF8(text);
if (str != NULL && (int)strlen(str) == col_offset) {
size = strlen(str);
}
Py_DECREF(text); Py_DECREF(text);
return size; return size;
} }
@ -366,7 +363,7 @@ void *
_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...) _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...)
{ {
Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1]; Token *t = p->known_err_token != NULL ? p->known_err_token : p->tokens[p->fill - 1];
int col_offset; Py_ssize_t col_offset;
if (t->col_offset == -1) { if (t->col_offset == -1) {
col_offset = Py_SAFE_DOWNCAST(p->tok->cur - p->tok->buf, col_offset = Py_SAFE_DOWNCAST(p->tok->cur - p->tok->buf,
intptr_t, int); intptr_t, int);
@ -386,7 +383,7 @@ _PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...)
void * void *
_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
int lineno, int col_offset, Py_ssize_t lineno, Py_ssize_t col_offset,
const char *errmsg, va_list va) const char *errmsg, va_list va)
{ {
PyObject *value = NULL; PyObject *value = NULL;
@ -406,16 +403,17 @@ _PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
if (!error_line) { if (!error_line) {
Py_ssize_t size = p->tok->inp - p->tok->buf; Py_ssize_t size = p->tok->inp - p->tok->buf;
if (size && p->tok->buf[size-1] == '\n') {
size--;
}
error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace"); error_line = PyUnicode_DecodeUTF8(p->tok->buf, size, "replace");
if (!error_line) { if (!error_line) {
goto error; goto error;
} }
} }
Py_ssize_t col_number = byte_offset_to_character_offset(error_line, col_offset); Py_ssize_t col_number = col_offset;
if (p->tok->encoding != NULL) {
col_number = byte_offset_to_character_offset(error_line, col_offset);
}
tmp = Py_BuildValue("(OiiN)", p->tok->filename, lineno, col_number, error_line); tmp = Py_BuildValue("(OiiN)", p->tok->filename, lineno, col_number, error_line);
if (!tmp) { if (!tmp) {

View File

@ -34,7 +34,7 @@ typedef struct _memo {
typedef struct { typedef struct {
int type; int type;
PyObject *bytes; PyObject *bytes;
int lineno, col_offset, end_lineno, end_col_offset; Py_ssize_t lineno, col_offset, end_lineno, end_col_offset;
Memo *memo; Memo *memo;
} Token; } Token;
@ -132,7 +132,7 @@ void *_PyPegen_string_token(Parser *p);
const char *_PyPegen_get_expr_name(expr_ty); const char *_PyPegen_get_expr_name(expr_ty);
void *_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...); void *_PyPegen_raise_error(Parser *p, PyObject *errtype, const char *errmsg, ...);
void *_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, void *_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype,
int lineno, int col_offset, Py_ssize_t lineno, Py_ssize_t col_offset,
const char *errmsg, va_list va); const char *errmsg, va_list va);
void *_PyPegen_dummy_name(Parser *p, ...); void *_PyPegen_dummy_name(Parser *p, ...);