Repository: Kinto/kinto

Issue:
Crash when querystring contains null character
``` python
Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.get(u"http://localhost:8888/v1/buckets?_since=\u0000", auth=("user","pass"))
<Response [500]>
>>> 

```

```
  File "/home/mathieu/Code/Mozilla/kinto/.venv/local/lib/python2.7/site-packages/pyramid/viewderivers.py", line 442, in rendered_view
    result = view(context, request)
  File "/home/mathieu/Code/Mozilla/kinto/.venv/local/lib/python2.7/site-packages/pyramid/viewderivers.py", line 147, in _requestonly_view
    response = view(request)
  File "/home/mathieu/Code/Mozilla/kinto/.venv/local/lib/python2.7/site-packages/cornice/service.py", line 489, in wrapper
    response = view_()
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/resource/__init__.py", line 254, in collection_get

  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/resource/__init__.py", line 1123, in _extract_filters
    # In base resource, PATCH only hit storage if no data has changed.
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/resource/__init__.py", line 913, in _extract_filters
    'location': 'querystring',
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/utils.py", line 149, in native_value
    try:
  File "/usr/lib/python2.7/ast.py", line 49, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/lib/python2.7/ast.py", line 37, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
TypeError: compile() expected string without null bytes lang=None uid=35e9c5ff6b7d9d89e0c52f8d1da20e2965747ddc812d01b895592a1e98dc1aad

```

Catching `TypeError` in `core.utils.native_value()` should be enough

Crash when querystring contains null character
``` python
Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.get(u"http://localhost:8888/v1/buckets?_since=\u0000", auth=("user","pass"))
<Response [500]>
>>> 

```

```
  File "/home/mathieu/Code/Mozilla/kinto/.venv/local/lib/python2.7/site-packages/pyramid/viewderivers.py", line 442, in rendered_view
    result = view(context, request)
  File "/home/mathieu/Code/Mozilla/kinto/.venv/local/lib/python2.7/site-packages/pyramid/viewderivers.py", line 147, in _requestonly_view
    response = view(request)
  File "/home/mathieu/Code/Mozilla/kinto/.venv/local/lib/python2.7/site-packages/cornice/service.py", line 489, in wrapper
    response = view_()
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/resource/__init__.py", line 254, in collection_get

  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/resource/__init__.py", line 1123, in _extract_filters
    # In base resource, PATCH only hit storage if no data has changed.
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/resource/__init__.py", line 913, in _extract_filters
    'location': 'querystring',
  File "/home/mathieu/Code/Mozilla/kinto/kinto/core/utils.py", line 149, in native_value
    try:
  File "/usr/lib/python2.7/ast.py", line 49, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/lib/python2.7/ast.py", line 37, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
TypeError: compile() expected string without null bytes lang=None uid=35e9c5ff6b7d9d89e0c52f8d1da20e2965747ddc812d01b895592a1e98dc1aad

```

Catching `TypeError` in `core.utils.native_value()` should be enough



Discussion:

Resolving patch:
diff --git a/kinto/core/utils.py b/kinto/core/utils.py
--- a/kinto/core/utils.py
+++ b/kinto/core/utils.py
@@ -148,7 +148,7 @@ def native_value(value):
             value = False
         try:
             return ast.literal_eval(value)
-        except (ValueError, SyntaxError):
+        except (TypeError, ValueError, SyntaxError):
             pass
     return value
 


Test patch:
diff --git a/tests/core/test_utils.py b/tests/core/test_utils.py
--- a/tests/core/test_utils.py
+++ b/tests/core/test_utils.py
@@ -59,6 +59,9 @@ def test_non_string_values(self):
         self.assertEqual(native_value(7), 7)
         self.assertEqual(native_value(True), True)
 
+    def test_bad_string_values(self):
+        self.assertEqual(native_value("\u0000"), "\x00")
+
 
 class StripWhitespaceTest(unittest.TestCase):
     def test_removes_all_kinds_of_spaces(self):