Безопасный анализатор выражений в Python

Как я могу позволить пользователям безопасно выполнять математические выражения? Нужно ли писать полный анализатор?

Есть ли что-то вроде ast.literal_eval () , но для выражений?

14
задан Ivo Danihelka 27 August 2010 в 11:26
поделиться

5 ответов

На странице Примеры Pyparsing перечислены несколько парсеров выражений:

http://pyparsing.wikispaces.com/file/view/fourFn.py - A реализация парсера/оценщика обычной арифметической инфиксной нотации с использованием pyparsing (несмотря на название, на самом деле это 5-функция арифметики плюс несколько триггерных функций)

http://pyparsing.wikispaces.com/file/view/simpleBool.py — парсер/оценщик логической инфиксной нотации, использующий вспомогательный метод pyparsing operatorPrecedence, который упрощает определение нотации инфиксных операторов

http://pyparsing.wikispaces.com/file/view/simpleArith. py http://pyparsing.wikispaces.com/file/view/eval_arith.py - Пара примеров преобразования FourFn.py с использованием operatorPrecedence. Первый просто анализирует и возвращает дерево разбора, второй добавляет логику оценки.

10
ответ дан 1 December 2019 в 14:31
поделиться

Да. Даже если бы существовал эквивалент ast.literal_eval() для выражений, выражение Python может быть множеством других вещей, кроме чисто математического выражения, например вызовом произвольной функции.

Меня не удивит, если в каком-нибудь модуле с открытым исходным кодом уже есть хороший анализатор/оценщик математических выражений, но если нет, то довольно легко написать свой собственный.

0
ответ дан 1 December 2019 в 14:31
поделиться

Несколько недель назад я сделал нечто подобное, но для логических выражений (или, и, не, сравнения, круглые скобки и т.д.). Я сделал это, используя парсер Ply. Я создал простой лексер и парсер. Парсер сгенерировал дерево AST, которое позже использовалось для выполнения вычислений. Выполнение этого таким образом позволит вам полностью контролировать то, что вводит пользователь, потому что будут анализироваться только выражения, совместимые с грамматикой.

1
ответ дан 1 December 2019 в 14:31
поделиться

математические функции будут состоять из цифр и знаков препинания, возможно, 'E' или 'e' если вы разрешите научную запись для рациональных чисел, и единственное (другое) законное использование альфа-символов будет, если вы разрешите/предоставите определенные математические функции (например, stddev). Таким образом, должно быть тривиально пробежаться по строке для альфа-символов и проверить, не является ли следующий бит подозрительным, а затем просто проверить строку в блоке try/except.

Что касается комментариев, которые получил этот ответ... Я согласен, что такой подход — игра с огнем. Тем не менее, это не означает, что это нельзя сделать безопасно. Я новичок в python (< 2 месяцев), поэтому, возможно, не знаю обходных путей, к которым это уязвимо (и, конечно, новая версия Python всегда может сделать код небезопасным в будущем), но - для чего это стоит ( в основном мое собственное развлечение) - вот мой щелчок по этому поводу:

def evalMaths(s):
    i = 0
    while i < len(s):
        while s[i].isalpha() and i < len(s):
            idn += s[i]
            i += 1
        if (idn and idn != 'e' and idn != 'abs' and idn != 'round'):
            raise Exception("you naughty boy: don't " + repr(idn))
        else:
            i += 1
    return eval(s)

Мне было бы очень интересно услышать, можно ли/как это обойти... (^_^) Кстати, я знаю, что вы можете вызывать такие функции, как abs2783 или _983 - если бы они существовали, но их не будет. Я имею в виду что-то практичное.

На самом деле, если кто-то может это сделать, я создам вопрос с вознаграждением в 200 и приму их ответ.

-1
ответ дан 1 December 2019 в 14:31
поделиться

Какие выражения вам нужны? Присвоение переменной? Оценка функции?

SymPy стремится стать полноценной Python CAS.

3
ответ дан 1 December 2019 в 14:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: