Ingen eval
krävs. Ditt problem är att du inte avkodar värdet som ett 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)
Inte bara det, utan att använda eval
för att avkoda json
är farligt och opålitligt. Det är opålitligt eftersom json
är inte Python, det råkar bara utvärdera lite som det mycket av tiden. Det är osäkert eftersom du aldrig vet vad du kan utvärdera. I det här fallet är du till stor del skyddad av 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 jag blir inte alls förvånad om någon kan tappa en eval
utnyttja förbi det. Så lektionen här:använd inte eval
.