Opened 4 weeks ago
Last modified 4 weeks ago
#35842 new Bug
JSONField has_key, has_keys, has_any_keys lookups do not properly handle quotes on Oracle and SQLite
Reported by: | Simon Charette | Owned by: | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 5.0 |
Severity: | Normal | Keywords: | oracle sqlite json key quote |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The following test reproduces issues on both Oracle and SQLite
-
tests/model_fields/test_jsonfield.py
diff --git a/tests/model_fields/test_jsonfield.py b/tests/model_fields/test_jsonfield.py index ff42b1a14c..b1090b30ac 100644
a b def test_has_key_number(self): 636 636 [obj], 637 637 ) 638 638 639 def test_has_key_special_chars(self): 640 value = { 641 'double"': "", 642 "single'": "", 643 "dollar$": "", 644 "mixed$\"'.": "", 645 } 646 obj = NullableJSONModel.objects.create( 647 value=value 648 ) 649 obj.refresh_from_db() 650 self.assertEqual(obj.value, value) 651 for key in value: 652 with self.subTest(key=key): 653 self.assertSequenceEqual( 654 NullableJSONModel.objects.filter(value__has_key=key), 655 [obj], 656 ) 657 639 658 @skipUnlessDBFeature("supports_json_field_contains") 640 659 def test_contains(self): 641 660 tests = [
In the case of Oracle the issue arise because it doesn't supporting binding variables in JSON_EXISTS
(original discussion) so while the json.dumps
of the key is believed to protect from SQL injections it can still result in crashes if the key contains a single quote character. Using the PASSING
clause could possibly allow us to bypass this limitation or using a different escaping strategy could possibly be used to adjust the Oracle implementation.
---
In the case of SQLite the problem is with the double-quote character "
because escapes generated by json.dumps
are not properly interpreted by SQLite.
In other words "foo\"bar"
is not properly interpreted as 'foo"bar
and while SQLite allows you not to quote keys (e.g. JSON_TYPE(%s, '$.foo\"bar') IS NOT NULL
) the solution is not viable for keys that contain both a double-quote and a symbol such as .
as exemplified by the mixed key in the provide test.
Change History (2)
comment:1 by , 4 weeks ago
comment:2 by , 4 weeks ago
Triage Stage: | Unreviewed → Accepted |
---|
It's related to the #32213.