This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: PyCode_Optimize() (peephole optimizer) doesn't handle KeyboardInterrupt correctly
Type: crash Stage: resolved
Components: Interpreter Core Versions: Python 3.7, Python 3.6, Python 3.5, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: pitrou, serhiy.storchaka, vstinner
Priority: normal Keywords:

Created on 2015-12-09 08:03 by vstinner, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 1078 closed louielu, 2017-04-11 08:08
Messages (5)
msg256143 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-12-09 08:03
The peephole optimizer computes 2**(2**100), but if I press CTRL+c (the result will probably kills my memory anyway), I get an assertion error (with a Python compiled in debug mode).

$ ./python
>>> 2**(2**100)
^C
python: Python/ceval.c:1218: PyEval_EvalFrameEx: Assertion `!PyErr_Occurred()' failed.
Abandon (core dumped)

fold_binops_on_constants() returns 0 with an exception (KeyboardInterrupt) raised. The problem is in the caller which doesn't handle the exception properly:

                if (h >= 0 &&
                    ISBASICBLOCK(blocks, h, i-h+1)  &&
                    fold_binops_on_constants(&codestr[i], consts, CONST_STACK_LASTN(2))) {
                    i -= 2;
                    memset(&codestr[h], NOP, i - h);
                    assert(codestr[i] == LOAD_CONST);
                    CONST_STACK_POP(2);
                    CONST_STACK_PUSH_OP(i);
                }

There is probably the same error on fold_unaryops_on_constants().


Python 2.7 looks to behave correctly:

$ python2.7
>>> 2**(2**100)
^C
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt


But in fact Python 2.7 is much worse :-D Peephole optimizer of Python 2.7 clears *all* exceptions (!) and it only optimizes 2**100, but not 2**(2**100). That's why the bug is not easily reproduced on Python 2.7. fold_binops_on_constants():

    if (newconst == NULL) {
        if(!PyErr_ExceptionMatches(PyExc_KeyboardInterrupt))
            PyErr_Clear();
        return 0;
    }
msg256144 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-12-09 08:24
FYI.

> Peephole optimizer of Python 2.7 (...) only optimizes 2**100, but not 2**(2**100).

This optimizer is dummy, it's only able to replace "LOAD_CONST x; LOAD_CONST y; OPERATION" with the result, whereas the optimizer replaces the bytecode with "NOP; NOP; NOP; NOP; LOAD_CONST z".

So "LOAD_CONST x; LOAD_CONST y; LOAD_CONST z; OPERATION1; OPERATION2" cannot be optimized. But it's enough to optimize 1+2+3 or 1*2*3 for example.

Python 3 peephole optimize does better thanks to a better design:
---
changeset:   68375:14205d0fee45
user:        Antoine Pitrou <solipsis@pitrou.net>
date:        Fri Mar 11 17:27:02 2011 +0100
files:       Lib/test/test_peepholer.py Misc/NEWS Python/peephole.c
description:
Issue #11244: The peephole optimizer is now able to constant-fold
arbitrarily complex expressions.  This also fixes a 3.2 regression where
operations involving negative numbers were not constant-folded.
---

It uses a stack for constants, so it's able to optimize more cases.
msg314244 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-03-22 10:15
I can reproduce a crash in 3.5, but not in 3.6. Seems it was fixed in issue30416.
msg321411 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-07-11 07:14
Can this issue be closed now?
msg321438 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2018-07-11 10:50
Yeah, let's close this issue.
History
Date User Action Args
2022-04-11 14:58:24adminsetgithub: 70014
2018-07-11 10:50:07vstinnersetstatus: open -> closed
resolution: fixed
messages: + msg321438

stage: needs patch -> resolved
2018-07-11 07:14:38serhiy.storchakasetmessages: + msg321411
2018-03-22 10:15:50serhiy.storchakasetmessages: + msg314244
2017-04-11 08:08:51louielusetpull_requests: + pull_request1221
2017-04-11 07:51:51louielusetversions: + Python 3.7
2015-12-09 17:51:14rhettingersetnosy: + pitrou
2015-12-09 08:24:47vstinnersetmessages: + msg256144
2015-12-09 08:15:20serhiy.storchakasetnosy: + serhiy.storchaka

components: + Interpreter Core
stage: needs patch
2015-12-09 08:03:24vstinnercreate