summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Ippolito <bob@redivi.com>2008-03-25 02:43:59 +0000
committerBob Ippolito <bob@redivi.com>2008-03-25 02:43:59 +0000
commit8b57d87e276c6031457873847d96542294a34cfe (patch)
tree95043462692ff35026b7a3679c2698db00266b4e
parent5d360053b7b6483978a82852dd7032bc30deaf97 (diff)
downloadsimplejson-8b57d87e276c6031457873847d96542294a34cfe.tar.gz
bump version, resolve http://code.google.com/p/simplejson/issues/detail?id=3
git-svn-id: http://simplejson.googlecode.com/svn/trunk@80 a4795897-2c25-0410-b006-0d3caba88fa1
-rw-r--r--setup.py2
-rw-r--r--simplejson/__init__.py2
-rw-r--r--simplejson/_speedups.c21
-rw-r--r--simplejson/decoder.py19
-rw-r--r--simplejson/tests/test_fail.py2
5 files changed, 32 insertions, 14 deletions
diff --git a/setup.py b/setup.py
index 7fbd436..082023f 100644
--- a/setup.py
+++ b/setup.py
@@ -18,7 +18,7 @@ from distutils.command.build_ext import build_ext
from distutils.errors import CCompilerError, DistutilsExecError, \
DistutilsPlatformError
-VERSION = '1.8.1'
+VERSION = '1.8.2'
DESCRIPTION = "Simple, fast, extensible JSON encoder/decoder for Python"
LONG_DESCRIPTION = """
simplejson is a simple, fast, complete, correct and extensible
diff --git a/simplejson/__init__.py b/simplejson/__init__.py
index be9e87a..94b94f8 100644
--- a/simplejson/__init__.py
+++ b/simplejson/__init__.py
@@ -99,7 +99,7 @@ pretty-print::
Note that the JSON produced by this module's default settings
is a subset of YAML, so it may be used as a serializer for that as well.
"""
-__version__ = '1.8.1'
+__version__ = '1.8.2'
__all__ = [
'dump', 'dumps', 'load', 'loads',
'JSONDecoder', 'JSONEncoder',
diff --git a/simplejson/_speedups.c b/simplejson/_speedups.c
index c7a7a7c..7021b21 100644
--- a/simplejson/_speedups.c
+++ b/simplejson/_speedups.c
@@ -239,7 +239,7 @@ join_list_unicode(PyObject *lst) {
}
static PyObject *
-scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding) {
+scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding, int strict) {
PyObject *rval;
Py_ssize_t len = PyString_GET_SIZE(pystr);
Py_ssize_t begin = end - 1;
@@ -257,6 +257,9 @@ scanstring_str(PyObject *pystr, Py_ssize_t end, char *encoding) {
c = buf[next];
if (c == '"' || c == '\\') {
break;
+ } else if (strict && c <= 0x1f) {
+ raise_errmsg("Invalid control character at", pystr, begin);
+ goto bail;
}
}
if (!(c == '"' || c == '\\')) {
@@ -397,7 +400,7 @@ bail:
static PyObject *
-scanstring_unicode(PyObject *pystr, Py_ssize_t end) {
+scanstring_unicode(PyObject *pystr, Py_ssize_t end, int strict) {
PyObject *rval;
Py_ssize_t len = PyUnicode_GET_SIZE(pystr);
Py_ssize_t begin = end - 1;
@@ -415,6 +418,9 @@ scanstring_unicode(PyObject *pystr, Py_ssize_t end) {
c = buf[next];
if (c == '"' || c == '\\') {
break;
+ } else if (strict && c <= 0x1f) {
+ raise_errmsg("Invalid control character at", pystr, begin);
+ goto bail;
}
}
if (!(c == '"' || c == '\\')) {
@@ -559,11 +565,12 @@ static PyObject *
py_scanstring(PyObject* self UNUSED, PyObject *args) {
PyObject *pystr;
Py_ssize_t end;
- char *encoding;
+ char *encoding = NULL;
+ int strict = 0;
#if PY_VERSION_HEX < 0x02050000
- if (!PyArg_ParseTuple(args, "Oiz:scanstring", &pystr, &end, &encoding)) {
+ if (!PyArg_ParseTuple(args, "Oi|zi:scanstring", &pystr, &end, &encoding, &strict)) {
#else
- if (!PyArg_ParseTuple(args, "Onz:scanstring", &pystr, &end, &encoding)) {
+ if (!PyArg_ParseTuple(args, "On|zi:scanstring", &pystr, &end, &encoding, &strict)) {
#endif
return NULL;
}
@@ -571,9 +578,9 @@ py_scanstring(PyObject* self UNUSED, PyObject *args) {
encoding = DEFAULT_ENCODING;
}
if (PyString_Check(pystr)) {
- return scanstring_str(pystr, end, encoding);
+ return scanstring_str(pystr, end, encoding, strict);
} else if (PyUnicode_Check(pystr)) {
- return scanstring_unicode(pystr, end);
+ return scanstring_unicode(pystr, end, strict);
}
PyErr_SetString(PyExc_TypeError, "first argument must be a string");
return NULL;
diff --git a/simplejson/decoder.py b/simplejson/decoder.py
index 6a73e9a..6d4c5d7 100644
--- a/simplejson/decoder.py
+++ b/simplejson/decoder.py
@@ -70,7 +70,7 @@ def JSONNumber(match, context):
return res, None
pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(JSONNumber)
-STRINGCHUNK = re.compile(r'(.*?)(["\\])', FLAGS)
+STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
BACKSLASH = {
'"': u'"', '\\': u'\\', '/': u'/',
'b': u'\b', 'f': u'\f', 'n': u'\n', 'r': u'\r', 't': u'\t',
@@ -78,7 +78,7 @@ BACKSLASH = {
DEFAULT_ENCODING = "utf-8"
-def scanstring(s, end, encoding=None, _b=BACKSLASH, _m=STRINGCHUNK.match):
+def scanstring(s, end, encoding=None, strict=True, _b=BACKSLASH, _m=STRINGCHUNK.match):
if encoding is None:
encoding = DEFAULT_ENCODING
chunks = []
@@ -97,6 +97,12 @@ def scanstring(s, end, encoding=None, _b=BACKSLASH, _m=STRINGCHUNK.match):
_append(content)
if terminator == '"':
break
+ elif terminator != '\\':
+ if strict:
+ raise ValueError(errmsg("Invalid control character %r at", s, end))
+ else:
+ _append(terminator)
+ continue
try:
esc = s[end]
except IndexError:
@@ -140,7 +146,8 @@ if _speedups is not None:
def JSONString(match, context):
encoding = getattr(context, 'encoding', None)
- return scanstring(match.string, match.end(), encoding)
+ strict = getattr(context, 'strict', True)
+ return scanstring(match.string, match.end(), encoding, strict)
pattern(r'"')(JSONString)
WHITESPACE = re.compile(r'\s*', FLAGS)
@@ -157,9 +164,10 @@ def JSONObject(match, context, _w=WHITESPACE.match):
raise ValueError(errmsg("Expecting property name", s, end))
end += 1
encoding = getattr(context, 'encoding', None)
+ strict = getattr(context, 'strict', True)
iterscan = JSONScanner.iterscan
while True:
- key, end = scanstring(s, end, encoding)
+ key, end = scanstring(s, end, encoding, strict)
end = _w(s, end).end()
if s[end:end + 1] != ':':
raise ValueError(errmsg("Expecting : delimiter", s, end))
@@ -257,7 +265,7 @@ class JSONDecoder(object):
__all__ = ['__init__', 'decode', 'raw_decode']
def __init__(self, encoding=None, object_hook=None, parse_float=None,
- parse_int=None, parse_constant=None):
+ parse_int=None, parse_constant=None, strict=True):
"""
``encoding`` determines the encoding used to interpret any ``str``
objects decoded by this instance (utf-8 by default). It has no
@@ -291,6 +299,7 @@ class JSONDecoder(object):
self.parse_float = parse_float
self.parse_int = parse_int
self.parse_constant = parse_constant
+ self.strict = strict
def decode(self, s, _w=WHITESPACE.match):
"""
diff --git a/simplejson/tests/test_fail.py b/simplejson/tests/test_fail.py
index a99d9c4..9534a94 100644
--- a/simplejson/tests/test_fail.py
+++ b/simplejson/tests/test_fail.py
@@ -48,6 +48,8 @@ JSONDOCS = [
'["Bad value", truth]',
# http://json.org/JSON_checker/test/fail24.json
"['single quote']",
+ # http://code.google.com/p/simplejson/issues/detail?id=3
+ u'["A\u001FZ control characters in string"]',
]
SKIPS = {