]> granicus.if.org Git - python/commitdiff
SF bug #1053819: Segfault in tuple_of_constants
authorRaymond Hettinger <python@rcn.com>
Tue, 26 Oct 2004 08:59:14 +0000 (08:59 +0000)
committerRaymond Hettinger <python@rcn.com>
Tue, 26 Oct 2004 08:59:14 +0000 (08:59 +0000)
Peepholer could be fooled into misidentifying a tuple_of_constants.
Added code to count consecutive occurrences of LOAD_CONST.
Use the count to weed out the misidentified cases.
Added a unittest.

Lib/test/test_peepholer.py
Python/compile.c

index 913f805e12a73e4c2fcba76b77184666fe9a3690..934b57c1e8d238fcb688535db7315b7db153550a 100644 (file)
@@ -83,6 +83,23 @@ class TestTranforms(unittest.TestCase):
             self.assert_(elem in asm)
             self.assert_('BUILD_TUPLE' not in asm)
 
+        # Bug 1053819:  Tuple of constants misidentified when presented with:
+        # . . . opcode_with_arg 100   unary_opcode   BUILD_TUPLE 1  . . .
+        # The following would segfault upon compilation
+        def crater():
+            (~[
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+            ],)
+
     def test_elim_extra_return(self):
         # RETURN LOAD_CONST None RETURN  -->  RETURN
         def f(x):
index dfb94d38e31d8607cf6f03acddf8d99a49c480ae..37793caaacd674d2b2a36ad72b7c17a270eeecb2 100644 (file)
@@ -419,15 +419,16 @@ tuple_of_constants(unsigned char *codestr, int n, PyObject *consts)
        newconst = PyTuple_New(n);
        if (newconst == NULL)
                return 0;
+       len_consts = PyList_GET_SIZE(consts);
        for (i=0 ; i<n ; i++) {
                arg = GETARG(codestr, (i*3));
+               assert(arg < len_consts);
                constant = PyList_GET_ITEM(consts, arg);
                Py_INCREF(constant);
                PyTuple_SET_ITEM(newconst, i, constant);
        }
 
        /* Append folded constant onto consts */
-       len_consts = PyList_GET_SIZE(consts);
        if (PyList_Append(consts, newconst)) {
                Py_DECREF(newconst);
                return 0;
@@ -501,6 +502,7 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
        unsigned char *lineno;
        int *addrmap = NULL;
        int new_line, cum_orig_line, last_line, tabsiz;
+       int cumlc=0, lastlc=0;  /* Count runs of consecutive LOAD_CONST codes */
        unsigned int *blocks;
        char *name;
 
@@ -536,6 +538,10 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
        for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
                addrmap[i] = i - nops;
                opcode = codestr[i];
+
+               lastlc = cumlc;
+               cumlc = 0;
+
                switch (opcode) {
 
                /* Replace UNARY_NOT JUMP_IF_FALSE POP_TOP with 
@@ -589,6 +595,7 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
 
                /* Skip over LOAD_CONST trueconst  JUMP_IF_FALSE xx  POP_TOP */
                case LOAD_CONST:
+                       cumlc = lastlc + 1;
                        j = GETARG(codestr, i);
                        if (codestr[i+3] != JUMP_IF_FALSE  ||
                            codestr[i+6] != POP_TOP  ||
@@ -607,6 +614,7 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
                        j = GETARG(codestr, i);
                        h = i - 3 * j;
                        if (h >= 0  &&
+                           j == lastlc  &&
                            codestr[h] == LOAD_CONST  && 
                            ISBASICBLOCK(blocks, h, 3*(j+1))  &&
                            tuple_of_constants(&codestr[h], j, consts)) {