Không có eval
bắt buộc. Vấn đề của bạn là bạn không giải mã giá trị dưới dạng đối tượng json.
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)
Không chỉ vậy, mà còn sử dụng eval
để giải mã json
là nguy hiểm và không đáng tin cậy. Nó không đáng tin cậy vì json
không phải là Python, nó chỉ xảy ra để đánh giá một chút giống như nó thường xuyên. Nó không an toàn bởi vì bạn không bao giờ biết những gì bạn có thể đang đánh giá. Trong trường hợp này, bạn được bảo vệ phần lớn bởi trình phân tích cú pháp json của 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__...
... nhưng tôi sẽ không ngạc nhiên nếu ai đó có thể trượt eval
khai thác quá khứ đó. Vì vậy, bài học ở đây:không sử dụng eval
.