По сути, единственный способ сделать это - разобрать его самостоятельно. Вы перемещаетесь по дереву разбора, чтобы гарантировать, что каждая часть находится в белом списке совершенно безобидных и безопасных операций, что делает все выражение безопасным по построению. Ответ Неда Батчелдера - это (простая) форма этого. После этого вы можете передать его eval()
, но какой в этом смысл? Вы можете вычислить значение каждого подвыражения как часть проверки (это особенно хорошая идея, потому что это делает ваш анализатор устойчивым к изменениям синтаксиса Python и т. Д.). Этот белый список должен быть очень маленьким, и есть много вещей, которые вы можете считать нормальными, но это не так (например, оператор общего вызова; функция getattr). Вы должны быть очень осторожны.
Черный список абсолютно исключен (например, предложение «отклонить подозрительные записи»). Откажитесь от всего, что не очевидно хорошо. Если вы этого не сделаете, это будет тривиально обойти ваш фильтр и дать выражение, которое делает что-то плохое, исключая маловероятную вероятность того, что ваш код лучше, чем любой другой черный список фильтров для Python, когда-либо созданных.
Были попытки ограничить выполнение Python, одна из них печально известна и теперь отключена (потому что она не работает) rexec модуль (и компания), а другая - песочница PyPy . Этот второй вариант не делает то, что вы просили, но, безусловно, стоит рассмотреть. Это, вероятно, то, что я бы использовал - это просто означает, что это будет не так просто, как eval(safematize(user_input))
.