Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cython
Commits
af9d9076
Commit
af9d9076
authored
Jul 02, 2021
by
da-woods
Committed by
GitHub
Jul 02, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix infinite recursion in binops code (GH-4204)
Closes
https://github.com/cython/cython/issues/4172
parent
875584d1
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
99 additions
and
11 deletions
+99
-11
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+6
-3
Cython/Utility/ExtensionTypes.c
Cython/Utility/ExtensionTypes.c
+1
-1
tests/run/binop_reverse_methods_GH2056.pyx
tests/run/binop_reverse_methods_GH2056.pyx
+92
-7
No files found.
Cython/Compiler/ModuleNode.py
View file @
af9d9076
...
...
@@ -2247,9 +2247,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"right, left"
if
reverse
else
"left, right"
,
extra_arg
)
else
:
return
'%s_maybe_call_slot(%s, left, right %s)'
%
(
return
'%s_maybe_call_slot(%s
->tp_base
, left, right %s)'
%
(
func_name
,
'Py_TYPE(right)->tp_base'
if
reverse
else
'Py_TYPE(left)->tp_base'
,
scope
.
parent_type
.
typeptr_cname
,
extra_arg
)
if
get_slot_method_cname
(
slot
.
left_slot
.
method_name
)
and
not
get_slot_method_cname
(
slot
.
right_slot
.
method_name
):
...
...
@@ -2260,13 +2260,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
slot
.
right_slot
.
method_name
,
))
overloads_left
=
int
(
bool
(
get_slot_method_cname
(
slot
.
left_slot
.
method_name
)))
overloads_right
=
int
(
bool
(
get_slot_method_cname
(
slot
.
right_slot
.
method_name
)))
code
.
putln
(
TempitaUtilityCode
.
load_as_string
(
"BinopSlot"
,
"ExtensionTypes.c"
,
context
=
{
"func_name"
:
func_name
,
"slot_name"
:
slot
.
slot_name
,
"overloads_left"
:
int
(
bool
(
get_slot_method_cname
(
slot
.
left_slot
.
method_name
))),
"overloads_left"
:
overloads_left
,
"overloads_right"
:
overloads_right
,
"call_left"
:
call_slot_method
(
slot
.
left_slot
.
method_name
,
reverse
=
False
),
"call_right"
:
call_slot_method
(
slot
.
right_slot
.
method_name
,
reverse
=
True
),
"type_cname"
:
scope
.
parent_type
.
typeptr_cname
,
...
...
Cython/Utility/ExtensionTypes.c
View file @
af9d9076
...
...
@@ -510,7 +510,7 @@ static PyObject *{{func_name}}(PyObject *left, PyObject *right {{extra_arg_decl}
}
if
(
maybe_self_is_left
)
{
PyObject
*
res
;
if
(
maybe_self_is_right
&&
!
({{
overloads_left
}}))
{
if
(
maybe_self_is_right
&&
{{
overloads_right
}}
&&
!
({{
overloads_left
}}))
{
res
=
{{
call_right
}};
if
(
res
!=
Py_NotImplemented
)
return
res
;
Py_DECREF
(
res
);
...
...
tests/run/binop_reverse_methods_GH2056.pyx
View file @
af9d9076
...
...
@@ -9,6 +9,15 @@ class Base(object):
>>> 2 + Base()
'Base.__radd__(Base(), 2)'
>>> Base(implemented=False) + 2 #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: unsupported operand type...
>>> 2 + Base(implemented=False) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: unsupported operand type...
>>> Base() ** 2
'Base.__pow__(Base(), 2, None)'
>>> 2 ** Base()
...
...
@@ -16,17 +25,34 @@ class Base(object):
>>> pow(Base(), 2, 100)
'Base.__pow__(Base(), 2, 100)'
"""
implemented
:
cython
.
bint
def
__init__
(
self
,
*
,
implemented
=
True
):
self
.
implemented
=
implemented
def
__add__
(
self
,
other
):
return
"Base.__add__(%s, %s)"
%
(
self
,
other
)
if
(
<
Base
>
self
).
implemented
:
return
"Base.__add__(%s, %s)"
%
(
self
,
other
)
else
:
return
NotImplemented
def
__radd__
(
self
,
other
):
return
"Base.__radd__(%s, %s)"
%
(
self
,
other
)
if
(
<
Base
>
self
).
implemented
:
return
"Base.__radd__(%s, %s)"
%
(
self
,
other
)
else
:
return
NotImplemented
def
__pow__
(
self
,
other
,
mod
):
return
"Base.__pow__(%s, %s, %s)"
%
(
self
,
other
,
mod
)
if
(
<
Base
>
self
).
implemented
:
return
"Base.__pow__(%s, %s, %s)"
%
(
self
,
other
,
mod
)
else
:
return
NotImplemented
def
__rpow__
(
self
,
other
,
mod
):
return
"Base.__rpow__(%s, %s, %s)"
%
(
self
,
other
,
mod
)
if
(
<
Base
>
self
).
implemented
:
return
"Base.__rpow__(%s, %s, %s)"
%
(
self
,
other
,
mod
)
else
:
return
NotImplemented
def
__repr__
(
self
):
return
"%s()"
%
(
self
.
__class__
.
__name__
)
...
...
@@ -44,9 +70,27 @@ class OverloadLeft(Base):
'OverloadLeft.__add__(OverloadLeft(), Base())'
>>> Base() + OverloadLeft()
'Base.__add__(Base(), OverloadLeft())'
>>> OverloadLeft(implemented=False) + Base(implemented=False) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: unsupported operand type...
>>> Base(implemented=False) + OverloadLeft(implemented=False) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: unsupported operand type...
"""
derived_implemented
:
cython
.
bint
def
__init__
(
self
,
*
,
implemented
=
True
):
super
().
__init__
(
implemented
=
implemented
)
self
.
derived_implemented
=
implemented
def
__add__
(
self
,
other
):
return
"OverloadLeft.__add__(%s, %s)"
%
(
self
,
other
)
if
(
<
OverloadLeft
>
self
).
derived_implemented
:
return
"OverloadLeft.__add__(%s, %s)"
%
(
self
,
other
)
else
:
return
NotImplemented
@
cython
.
c_api_binop_methods
(
False
)
...
...
@@ -62,9 +106,27 @@ class OverloadRight(Base):
'Base.__add__(OverloadRight(), Base())'
>>> Base() + OverloadRight()
'OverloadRight.__radd__(OverloadRight(), Base())'
>>> OverloadRight(implemented=False) + Base(implemented=False) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: unsupported operand type...
>>> Base(implemented=False) + OverloadRight(implemented=False) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: unsupported operand type...
"""
derived_implemented
:
cython
.
bint
def
__init__
(
self
,
*
,
implemented
=
True
):
super
().
__init__
(
implemented
=
implemented
)
self
.
derived_implemented
=
implemented
def
__radd__
(
self
,
other
):
return
"OverloadRight.__radd__(%s, %s)"
%
(
self
,
other
)
if
(
<
OverloadRight
>
self
).
derived_implemented
:
return
"OverloadRight.__radd__(%s, %s)"
%
(
self
,
other
)
else
:
return
NotImplemented
@
cython
.
c_api_binop_methods
(
True
)
@
cython
.
cclass
...
...
@@ -79,7 +141,30 @@ class OverloadCApi(Base):
'OverloadCApi.__add__(OverloadCApi(), Base())'
>>> Base() + OverloadCApi()
'OverloadCApi.__add__(Base(), OverloadCApi())'
>>> OverloadCApi(derived_implemented=False) + 2 #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: unsupported operand type...
>>> 2 + OverloadCApi(derived_implemented=False) #doctest: +ELLIPSIS
Traceback (most recent call last):
...
TypeError: unsupported operand type...
"""
derived_implemented
:
cython
.
bint
def
__init__
(
self
,
*
,
derived_implemented
=
True
):
super
().
__init__
(
implemented
=
True
)
self
.
derived_implemented
=
derived_implemented
def
__add__
(
self
,
other
):
return
"OverloadCApi.__add__(%s, %s)"
%
(
self
,
other
)
if
isinstance
(
self
,
OverloadCApi
):
derived_implemented
=
(
<
OverloadCApi
>
self
).
derived_implemented
else
:
derived_implemented
=
(
<
OverloadCApi
>
other
).
derived_implemented
if
derived_implemented
:
return
"OverloadCApi.__add__(%s, %s)"
%
(
self
,
other
)
else
:
return
NotImplemented
# TODO: Test a class that only defines the `__r...__()` methods.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment