summaryrefslogtreecommitdiffstats
path: root/Python/ast.c
diff options
context:
space:
mode:
authorEric V. Smith <eric@trueblade.com>2016-10-31 18:46:26 (GMT)
committerEric V. Smith <eric@trueblade.com>2016-10-31 18:46:26 (GMT)
commit5646648678295a44aa82636c6e92826651baf33a (patch)
tree2a41306ca416712ba7b55a4e51bcb836ab2a693c /Python/ast.c
parent7f0514ad54dd806817ce6d1f54969b8979475d34 (diff)
downloadcpython-5646648678295a44aa82636c6e92826651baf33a.zip
cpython-5646648678295a44aa82636c6e92826651baf33a.tar.gz
cpython-5646648678295a44aa82636c6e92826651baf33a.tar.bz2
Issue 28128: Print out better error/warning messages for invalid string escapes. Backport to 3.6.
Diffstat (limited to 'Python/ast.c')
-rw-r--r--Python/ast.c66
1 files changed, 61 insertions, 5 deletions
diff --git a/Python/ast.c b/Python/ast.c
index 76daf6f..91e7d01 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -4113,8 +4113,34 @@ decode_utf8(struct compiling *c, const char **sPtr, const char *end)
return PyUnicode_DecodeUTF8(t, s - t, NULL);
}
+static int
+warn_invalid_escape_sequence(struct compiling *c, const node *n,
+ char first_invalid_escape_char)
+{
+ PyObject *msg = PyUnicode_FromFormat("invalid escape sequence \\%c",
+ first_invalid_escape_char);
+ if (msg == NULL) {
+ return -1;
+ }
+ if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, msg,
+ c->c_filename, LINENO(n),
+ NULL, NULL) < 0 &&
+ PyErr_ExceptionMatches(PyExc_DeprecationWarning))
+ {
+ const char *s = PyUnicode_AsUTF8(msg);
+ if (s != NULL) {
+ ast_error(c, n, s);
+ }
+ Py_DECREF(msg);
+ return -1;
+ }
+ Py_DECREF(msg);
+ return 0;
+}
+
static PyObject *
-decode_unicode_with_escapes(struct compiling *c, const char *s, size_t len)
+decode_unicode_with_escapes(struct compiling *c, const node *n, const char *s,
+ size_t len)
{
PyObject *v, *u;
char *buf;
@@ -4167,11 +4193,41 @@ decode_unicode_with_escapes(struct compiling *c, const char *s, size_t len)
len = p - buf;
s = buf;
- v = PyUnicode_DecodeUnicodeEscape(s, len, NULL);
+ const char *first_invalid_escape;
+ v = _PyUnicode_DecodeUnicodeEscape(s, len, NULL, &first_invalid_escape);
+
+ if (v != NULL && first_invalid_escape != NULL) {
+ if (warn_invalid_escape_sequence(c, n, *first_invalid_escape) < 0) {
+ /* We have not decref u before because first_invalid_escape points
+ inside u. */
+ Py_XDECREF(u);
+ Py_DECREF(v);
+ return NULL;
+ }
+ }
Py_XDECREF(u);
return v;
}
+static PyObject *
+decode_bytes_with_escapes(struct compiling *c, const node *n, const char *s,
+ size_t len)
+{
+ const char *first_invalid_escape;
+ PyObject *result = _PyBytes_DecodeEscape(s, len, NULL, 0, NULL,
+ &first_invalid_escape);
+ if (result == NULL)
+ return NULL;
+
+ if (first_invalid_escape != NULL) {
+ if (warn_invalid_escape_sequence(c, n, *first_invalid_escape) < 0) {
+ Py_DECREF(result);
+ return NULL;
+ }
+ }
+ return result;
+}
+
/* Compile this expression in to an expr_ty. Add parens around the
expression, in order to allow leading spaces in the expression. */
static expr_ty
@@ -4310,7 +4366,7 @@ done:
literal_end-literal_start,
NULL, NULL);
else
- *literal = decode_unicode_with_escapes(c, literal_start,
+ *literal = decode_unicode_with_escapes(c, n, literal_start,
literal_end-literal_start);
if (!*literal)
return -1;
@@ -5048,12 +5104,12 @@ parsestr(struct compiling *c, const node *n, int *bytesmode, int *rawmode,
if (*rawmode)
*result = PyBytes_FromStringAndSize(s, len);
else
- *result = PyBytes_DecodeEscape(s, len, NULL, /* ignored */ 0, NULL);
+ *result = decode_bytes_with_escapes(c, n, s, len);
} else {
if (*rawmode)
*result = PyUnicode_DecodeUTF8Stateful(s, len, NULL, NULL);
else
- *result = decode_unicode_with_escapes(c, s, len);
+ *result = decode_unicode_with_escapes(c, n, s, len);
}
return *result == NULL ? -1 : 0;
}