Pull to refresh
23
0
Send message

Понял, спасибо! Javascript у меня очень эпизодический, но я стараюсь не отставать.

Я что-то упускаю? Какая строчка попахивает мамонтом?

Всё это требует интернета. Самое штатное из всех средств должно быть USB, как наикратчайший путь.

А не пофиг ли? Мы же не собираемся загруженный файл выполнять.

Чуваку в списке рассылки ещё более креативные способы предлагали. Своё облачное хранилище, например :) Но загрузчик мне и так пригодился бы, вот и решил совместить приятное с полезным.

Да, но идея была в том, чтобы от eval не отказываться. Про парсинг вручную есть у меня материал, этакий crash course, но он, сырой и, скорее, для детей. Не вижу смысла его тут публиковать.

bad saturday ¯_(ツ)_/¯

-    validate_children(tree.body)
+    validate_children(tree)

Да, забыл сказать, что ast.Expression тогда надо добавить в _allowed_nodes . Хотя, минимально достаточный патч для исправления этой баги будет таким:

                     raise Exception('Неправильное выражение')
                 validate_children(child)
 
-    validate_children(tree)
+    validate_children(tree.body)
 
 def dump(node):
     def _format(node, indent):

Поправил в статье, хотя вредительство уже успело расползтись.

Спасибо за +2 к миллиону глаз ?

'exec':None бесполезен, в __builtins__ много всякого, например eval("__builtins__.import('os').removedirs('test-test-test')")

— сейчас всё исправим, насяльника ?

Если посмотреть дерево для sin.__name__, то наблюдаем Attribute

AST Expression
body
    AST Attribute
    value
        AST Name
        id
            'sin'
        ctx
            AST Load
    attr
        '__name__'
    ctx
        AST Load

Я аж протёр глаза, и подумал что Attribute каким-то образом унаследован от Name, поэтому isinstance его пропускает и даже полез смотреть Python-ast.c как они это делают, но всё оказалось гораздо проще. Вот правильная (надеюсь) версия валидатора:

def validate_ast(node):
    for child in ast.iter_child_nodes(node):
        if isinstance(child, list):
            for grandchild in child:
                validate_ast(grandchild)
        else:
            if not isinstance(child, _allowed_nodes):
                raise Exception('Неправильное выражение')
            if isinstance(child, ast.Constant) and not isinstance(child.value, (int, float, complex)):
                raise Exception('Неправильное выражение')
            validate_ast(child)

А всё потому, что скопипастил из аналогичного проекта, но там у меня разрешались только Call и Constant.

Была также мысль запретить Name везде, кроме вызовов функций, но это усложнило бы валидатор, и нельзя было бы добавить в контекст математические константы pi, e, tau

Ага, со строками недоработка. Можно добавить в валидатор

if isinstance(child, ast.Constant) and not isinstance(child.value, (int, float, complex)):
    raise Exception('Неправильное выражение')

или попытаться преобразовать их в число как, это бывает в известных языках ?

Information

Rating
Does not participate
Registered
Activity