diff options
author | da-woods <dw-git@d-woods.co.uk> | 2020-01-08 10:44:20 +0000 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2020-01-08 11:44:20 +0100 |
commit | c2d76d3201603385d4d9d4780e1f0257056e8363 (patch) | |
tree | ae14c8fdec53cd11ba4758474a802a2a8b8fb0af | |
parent | dd64445f7b74338e911ead8c566e939a2d62cf52 (diff) | |
download | cython-c2d76d3201603385d4d9d4780e1f0257056e8363.tar.gz |
Fixed handling of kwds in generator closures (GH-3268)
-rw-r--r-- | Cython/Compiler/Nodes.py | 10 | ||||
-rw-r--r-- | tests/run/generators.pyx | 34 |
2 files changed, 42 insertions, 2 deletions
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index d97c1cc2a..b3525584d 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -3256,8 +3256,14 @@ class DefNode(FuncDefNode): def put_into_closure(entry): if entry.in_closure: code.putln('%s = %s;' % (entry.cname, entry.original_cname)) - code.put_var_incref(entry) - code.put_var_giveref(entry) + if entry.xdecref_cleanup: + # mostly applies to the starstar arg - this can sometimes be NULL + # so must be xincrefed instead + code.put_var_xincref(entry) + code.put_var_xgiveref(entry) + else: + code.put_var_incref(entry) + code.put_var_giveref(entry) for arg in self.args: put_into_closure(arg.entry) for arg in self.star_arg, self.starstar_arg: diff --git a/tests/run/generators.pyx b/tests/run/generators.pyx index f407739c8..1ba98fd8f 100644 --- a/tests/run/generators.pyx +++ b/tests/run/generators.pyx @@ -522,3 +522,37 @@ def test_generator_frame(a=1): """ b = a + 1 yield b + +# GH Issue 3265 - **kwds could cause a crash in some cases due to not +# handling NULL pointers (in testing it shows as a REFNANNY error). +# This was on creation of the generator and +# doesn't really require it to be iterated through: +def some_function(): + return 0 + +def test_generator_kwds1(**kwargs): + """ + >>> for a in test_generator_kwds1(): + ... print(a) + 0 + """ + yield some_function(**kwargs) + +def test_generator_kwds2(**kwargs): + """ + >>> for a in test_generator_kwds2(): + ... print(a) + 0 + """ + yield 0 + +def test_generator_kwds3(**kwargs): + """ + This didn't actually crash before but is still worth a try + >>> len(list(test_generator_kwds3())) + 0 + >>> for a in test_generator_kwds3(a=1): + ... print(a) + a + """ + yield from kwargs.keys() |