Geen eval
Is benodigd. Uw probleem is dat u de waarde niet als een json-object decodeert.
CREATE OR REPLACE FUNCTION json_update(data json, key text, value json)
RETURNS json AS
$BODY$
from json import loads, dumps
if key is None: return data
js = loads(data)
# you must decode 'value' with loads too:
js[key] = loads(value)
return dumps(js)
$BODY$
LANGUAGE plpythonu VOLATILE;
postgres=# SELECT json_update('{"a":1}', 'a', '{"innerkey":"innervalue"}');
json_update
-----------------------------------
{"a": {"innerkey": "innervalue"}}
(1 row)
Niet alleen dat, maar met behulp van eval
om json
te decoderen is gevaarlijk en onbetrouwbaar. Het is onbetrouwbaar omdat json
is Python niet, het evalueert gewoon een beetje zoals het vaak. Het is onveilig omdat je nooit weet wat je gaat evalueren. In dit geval wordt u grotendeels beschermd door de json-parser van PostgreSQL:
postgres=# SELECT json_update(
postgres(# '{"a":1}',
postgres(# 'a',
postgres(# '__import__(''shutil'').rmtree(''/glad_this_is_not_just_root'')'
postgres(# );
ERROR: invalid input syntax for type json
LINE 4: '__import__(''shutil'').rmtree(''/glad_this_is_not_...
^
DETAIL: Token "__import__" is invalid.
CONTEXT: JSON data, line 1: __import__...
... maar ik zal helemaal niet verbaasd zijn als iemand een eval
. kan geven daar voorbij uitbuiten. Dus de les hier:gebruik geen eval
.