diff options
| -rw-r--r-- | python/modules/cquoting.c | 29 | ||||
| -rw-r--r-- | python/skytools/_pyquoting.py | 9 |
2 files changed, 38 insertions, 0 deletions
diff --git a/python/modules/cquoting.c b/python/modules/cquoting.c index 2dcfc227..42844ca2 100644 --- a/python/modules/cquoting.c +++ b/python/modules/cquoting.c @@ -386,6 +386,33 @@ failed: return NULL; } +static PyObject *do_dolq(unsigned char *src, Py_ssize_t src_len) +{ + /* src_len >= 2, '$' in start and end */ + unsigned char *src_end = src + src_len; + unsigned char *p1 = src + 1, *p2 = src_end - 2; + + while (p1 < src_end && *p1 != '$') + p1++; + while (p2 > src && *p2 != '$') + p2--; + if (p2 <= p1) + goto failed; + + p1++; /* position after '$' */ + + if ((p1 - src) != (src_end - p2)) + goto failed; + if (memcmp(src, p2, p1 - src) != 0) + goto failed; + + return PyString_FromStringAndSize((char *)p1, p2 - p1); + +failed: + PyErr_Format(PyExc_ValueError, "Broken dollar-quoted string"); + return NULL; +} + static PyObject *unquote_literal(PyObject *self, PyObject *args) { unsigned char *src = NULL; @@ -400,6 +427,8 @@ static PyObject *unquote_literal(PyObject *self, PyObject *args) Py_INCREF(Py_None); return Py_None; } + if (src_len >= 2 && src[0] == '$' && src[src_len - 1] == '$') + return do_dolq(src, src_len); if (src_len < 2 || src[src_len - 1] != '\'') goto badstr; if (src[0] == '\'') { diff --git a/python/skytools/_pyquoting.py b/python/skytools/_pyquoting.py index 32d548ff..8f72eb5f 100644 --- a/python/skytools/_pyquoting.py +++ b/python/skytools/_pyquoting.py @@ -179,6 +179,15 @@ def unquote_literal(val, stdstr = False): return _esql_rc.sub(_sub_unescape_sqlext, val[1:-1]) elif len(val) > 2 and val[0] in ('E', 'e') and val[1] == "'" and val[-1] == "'": return _esql_rc.sub(_sub_unescape_sqlext, val[2:-1]) + elif len(val) >= 2 and val[0] == '$' and val[-1] == '$': + p1 = val.find('$', 1) + p2 = val.rfind('$', 1, -1) + if p1 > 0 and p2 > p1: + t1 = val[:p1+1] + t2 = val[p2:] + if t1 == t2: + return val[len(t1):-len(t1)] + raise Exception("Bad dollar-quoted string") elif val.lower() == "null": return None return val |
