Ingen eval
er påkrævet. Dit problem er, at du ikke afkoder værdien som et json-objekt.
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)
Ikke kun det, men ved at bruge eval
at afkode json
er farlig og upålidelig. Den er upålidelig, fordi json
er Python ikke, det tilfældigvis evaluerer lidt ligesom det meget af tiden. Det er usikkert, fordi du aldrig ved, hvad du kan evaluere. I dette tilfælde er du stort set beskyttet af PostgreSQL's json-parser:
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__...
... men jeg vil slet ikke blive overrasket, hvis nogen kan smide en eval
udnytte forbi det. Så lektionen her:Brug ikke eval
.