summaryrefslogtreecommitdiff
path: root/astroid/helpers.py
diff options
context:
space:
mode:
Diffstat (limited to 'astroid/helpers.py')
-rw-r--r--astroid/helpers.py24
1 files changed, 23 insertions, 1 deletions
diff --git a/astroid/helpers.py b/astroid/helpers.py
index 8ab68799..7a9fae17 100644
--- a/astroid/helpers.py
+++ b/astroid/helpers.py
@@ -1,6 +1,9 @@
# Copyright (c) 2015-2020 Claudiu Popa <pcmanticore@gmail.com>
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
+# Copyright (c) 2020 Simon Hewitt <si@sjhewitt.co.uk>
+# Copyright (c) 2020 Bryce Guinta <bryce.guinta@protonmail.com>
+# Copyright (c) 2020 Ram Rachum <ram@rachum.com>
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
@@ -237,13 +240,32 @@ def object_len(node, context=None):
:raises AstroidTypeError: If an invalid node is returned
from __len__ method or no __len__ method exists
:raises InferenceError: If the given node cannot be inferred
- or if multiple nodes are inferred
+ or if multiple nodes are inferred or if the code executed in python
+ would result in a infinite recursive check for length
:rtype int: Integer length of node
"""
# pylint: disable=import-outside-toplevel; circular import
from astroid.objects import FrozenSet
inferred_node = safe_infer(node, context=context)
+
+ # prevent self referential length calls from causing a recursion error
+ # see https://github.com/PyCQA/astroid/issues/777
+ node_frame = node.frame()
+ if (
+ isinstance(node_frame, scoped_nodes.FunctionDef)
+ and node_frame.name == "__len__"
+ and inferred_node is not None
+ and inferred_node._proxied == node_frame.parent
+ ):
+ message = (
+ "Self referential __len__ function will "
+ "cause a RecursionError on line {} of {}".format(
+ node.lineno, node.root().file
+ )
+ )
+ raise exceptions.InferenceError(message)
+
if inferred_node is None or inferred_node is util.Uninferable:
raise exceptions.InferenceError(node=node)
if isinstance(inferred_node, nodes.Const) and isinstance(