Drop eval-based json parser fallback

Drop potentially-unsafe eval-based json parser that was
used as a fallback in case simplejson and json were not
available. Let's assume people run Python 2.6 or can
install simplejson if they are not. Fixes bug 909568.

Change-Id: I1b1860a77de5075fcea291a4f1b320a3e9e6261f
This commit is contained in:
Thierry Carrez 2012-01-23 17:00:40 +01:00
parent 16a5faaaba
commit b23d2eb422
3 changed files with 5 additions and 102 deletions

View File

@ -71,38 +71,9 @@ try:
from simplejson import loads as json_loads from simplejson import loads as json_loads
from simplejson import dumps as json_dumps from simplejson import dumps as json_dumps
except ImportError: except ImportError:
try:
# 2.6 will have a json module in the stdlib # 2.6 will have a json module in the stdlib
from json import loads as json_loads from json import loads as json_loads
from json import dumps as json_dumps from json import dumps as json_dumps
except ImportError:
# fall back on local parser otherwise
comments = compile(r'/\*.*\*/|//[^\r\n]*', DOTALL)
def json_loads(string):
'''
Fairly competent json parser exploiting the python tokenizer and
eval(). -- From python-cloudfiles
_loads(serialized_json) -> object
'''
try:
res = []
consts = {'true': True, 'false': False, 'null': None}
string = '(' + comments.sub('', string) + ')'
for type, val, _junk, _junk, _junk in \
generate_tokens(StringIO(string).readline):
if (type == OP and val not in '[]{}:,()-') or \
(type == NAME and val not in consts):
raise AttributeError()
elif type == STRING:
res.append('u')
res.append(val.replace('\\/', '/'))
else:
res.append(val)
return eval(''.join(res), {}, consts)
except Exception:
raise AttributeError()
class ClientException(Exception): class ClientException(Exception):

View File

@ -57,37 +57,8 @@ try:
# simplejson is popular and pretty good # simplejson is popular and pretty good
from simplejson import loads as json_loads from simplejson import loads as json_loads
except ImportError: except ImportError:
try:
# 2.6 will have a json module in the stdlib # 2.6 will have a json module in the stdlib
from json import loads as json_loads from json import loads as json_loads
except ImportError:
# fall back on local parser otherwise
comments = compile(r'/\*.*\*/|//[^\r\n]*', DOTALL)
def json_loads(string):
'''
Fairly competent json parser exploiting the python tokenizer and
eval(). -- From python-cloudfiles
_loads(serialized_json) -> object
'''
try:
res = []
consts = {'true': True, 'false': False, 'null': None}
string = '(' + comments.sub('', string) + ')'
for type, val, _junk, _junk, _junk in \
generate_tokens(StringIO(string).readline):
if (type == OP and val not in '[]{}:,()-') or \
(type == NAME and val not in consts):
raise AttributeError()
elif type == STRING:
res.append('u')
res.append(val.replace('\\/', '/'))
else:
res.append(val)
return eval(''.join(res), {}, consts)
except Exception:
raise AttributeError()
class ClientException(Exception): class ClientException(Exception):

View File

@ -109,45 +109,6 @@ class TestJsonImport(unittest.TestCase):
else: else:
self.assertEquals(loads, c.json_loads) self.assertEquals(loads, c.json_loads)
def test_no_json(self):
# first break simplejson
try:
import simplejson
except ImportError:
# not installed, so we don't have to break it for these tests
pass
else:
delattr(simplejson, 'loads')
# then break json
try:
import json
except ImportError:
# not installed, so we don't have to break it for these tests
_orig_dumps = None
else:
# before we break json, grab a copy of the orig_dumps function
_orig_dumps = json.dumps
delattr(json, 'loads')
reload(c)
if _orig_dumps:
# basic test of swift.common.client.json_loads using json.loads
data = {
'string': 'value',
'int': 0,
'bool': True,
'none': None,
}
json_string = _orig_dumps(data)
else:
# even more basic test using a hand encoded json string
data = ['value1', 'value2']
json_string = "['value1', 'value2']"
self.assertEquals(data, c.json_loads(json_string))
self.assertRaises(AttributeError, c.json_loads, self)
class MockHttpTest(unittest.TestCase): class MockHttpTest(unittest.TestCase):