• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdbool.h>
2 
3 #include "Python.h"
4 #include "code.h"
5 #include "structmember.h"
6 
7 /* Holder for co_extra information */
8 typedef struct {
9     Py_ssize_t ce_size;
10     void *ce_extras[1];
11 } _PyCodeObjectExtra;
12 
13 /* all_name_chars(s): true iff s matches [a-zA-Z0-9_]* */
14 static int
all_name_chars(PyObject * o)15 all_name_chars(PyObject *o)
16 {
17     const unsigned char *s, *e;
18 
19     if (!PyUnicode_IS_ASCII(o))
20         return 0;
21 
22     s = PyUnicode_1BYTE_DATA(o);
23     e = s + PyUnicode_GET_LENGTH(o);
24     for (; s != e; s++) {
25         if (!Py_ISALNUM(*s) && *s != '_')
26             return 0;
27     }
28     return 1;
29 }
30 
31 static void
intern_strings(PyObject * tuple)32 intern_strings(PyObject *tuple)
33 {
34     Py_ssize_t i;
35 
36     for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
37         PyObject *v = PyTuple_GET_ITEM(tuple, i);
38         if (v == NULL || !PyUnicode_CheckExact(v)) {
39             Py_FatalError("non-string found in code slot");
40         }
41         PyUnicode_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
42     }
43 }
44 
45 /* Intern selected string constants */
46 static int
intern_string_constants(PyObject * tuple)47 intern_string_constants(PyObject *tuple)
48 {
49     int modified = 0;
50     Py_ssize_t i;
51 
52     for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
53         PyObject *v = PyTuple_GET_ITEM(tuple, i);
54         if (PyUnicode_CheckExact(v)) {
55             if (PyUnicode_READY(v) == -1) {
56                 PyErr_Clear();
57                 continue;
58             }
59             if (all_name_chars(v)) {
60                 PyObject *w = v;
61                 PyUnicode_InternInPlace(&v);
62                 if (w != v) {
63                     PyTuple_SET_ITEM(tuple, i, v);
64                     modified = 1;
65                 }
66             }
67         }
68         else if (PyTuple_CheckExact(v)) {
69             intern_string_constants(v);
70         }
71         else if (PyFrozenSet_CheckExact(v)) {
72             PyObject *w = v;
73             PyObject *tmp = PySequence_Tuple(v);
74             if (tmp == NULL) {
75                 PyErr_Clear();
76                 continue;
77             }
78             if (intern_string_constants(tmp)) {
79                 v = PyFrozenSet_New(tmp);
80                 if (v == NULL) {
81                     PyErr_Clear();
82                 }
83                 else {
84                     PyTuple_SET_ITEM(tuple, i, v);
85                     Py_DECREF(w);
86                     modified = 1;
87                 }
88             }
89             Py_DECREF(tmp);
90         }
91     }
92     return modified;
93 }
94 
95 
96 PyCodeObject *
PyCode_New(int argcount,int kwonlyargcount,int nlocals,int stacksize,int flags,PyObject * code,PyObject * consts,PyObject * names,PyObject * varnames,PyObject * freevars,PyObject * cellvars,PyObject * filename,PyObject * name,int firstlineno,PyObject * lnotab)97 PyCode_New(int argcount, int kwonlyargcount,
98            int nlocals, int stacksize, int flags,
99            PyObject *code, PyObject *consts, PyObject *names,
100            PyObject *varnames, PyObject *freevars, PyObject *cellvars,
101            PyObject *filename, PyObject *name, int firstlineno,
102            PyObject *lnotab)
103 {
104     PyCodeObject *co;
105     Py_ssize_t *cell2arg = NULL;
106     Py_ssize_t i, n_cellvars, n_varnames, total_args;
107 
108     /* Check argument types */
109     if (argcount < 0 || kwonlyargcount < 0 || nlocals < 0 ||
110         code == NULL || !PyBytes_Check(code) ||
111         consts == NULL || !PyTuple_Check(consts) ||
112         names == NULL || !PyTuple_Check(names) ||
113         varnames == NULL || !PyTuple_Check(varnames) ||
114         freevars == NULL || !PyTuple_Check(freevars) ||
115         cellvars == NULL || !PyTuple_Check(cellvars) ||
116         name == NULL || !PyUnicode_Check(name) ||
117         filename == NULL || !PyUnicode_Check(filename) ||
118         lnotab == NULL || !PyBytes_Check(lnotab)) {
119         PyErr_BadInternalCall();
120         return NULL;
121     }
122 
123     /* Ensure that the filename is a ready Unicode string */
124     if (PyUnicode_READY(filename) < 0)
125         return NULL;
126 
127     intern_strings(names);
128     intern_strings(varnames);
129     intern_strings(freevars);
130     intern_strings(cellvars);
131     intern_string_constants(consts);
132 
133     /* Check for any inner or outer closure references */
134     n_cellvars = PyTuple_GET_SIZE(cellvars);
135     if (!n_cellvars && !PyTuple_GET_SIZE(freevars)) {
136         flags |= CO_NOFREE;
137     } else {
138         flags &= ~CO_NOFREE;
139     }
140 
141     n_varnames = PyTuple_GET_SIZE(varnames);
142     if (argcount <= n_varnames && kwonlyargcount <= n_varnames) {
143         /* Never overflows. */
144         total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount +
145                 ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
146     }
147     else {
148         total_args = n_varnames + 1;
149     }
150     if (total_args > n_varnames) {
151         PyErr_SetString(PyExc_ValueError, "code: varnames is too small");
152         return NULL;
153     }
154 
155     /* Create mapping between cells and arguments if needed. */
156     if (n_cellvars) {
157         bool used_cell2arg = false;
158         cell2arg = PyMem_NEW(Py_ssize_t, n_cellvars);
159         if (cell2arg == NULL) {
160             PyErr_NoMemory();
161             return NULL;
162         }
163         /* Find cells which are also arguments. */
164         for (i = 0; i < n_cellvars; i++) {
165             Py_ssize_t j;
166             PyObject *cell = PyTuple_GET_ITEM(cellvars, i);
167             cell2arg[i] = CO_CELL_NOT_AN_ARG;
168             for (j = 0; j < total_args; j++) {
169                 PyObject *arg = PyTuple_GET_ITEM(varnames, j);
170                 int cmp = PyUnicode_Compare(cell, arg);
171                 if (cmp == -1 && PyErr_Occurred()) {
172                     PyMem_FREE(cell2arg);
173                     return NULL;
174                 }
175                 if (cmp == 0) {
176                     cell2arg[i] = j;
177                     used_cell2arg = true;
178                     break;
179                 }
180             }
181         }
182         if (!used_cell2arg) {
183             PyMem_FREE(cell2arg);
184             cell2arg = NULL;
185         }
186     }
187     co = PyObject_NEW(PyCodeObject, &PyCode_Type);
188     if (co == NULL) {
189         if (cell2arg)
190             PyMem_FREE(cell2arg);
191         return NULL;
192     }
193     co->co_argcount = argcount;
194     co->co_kwonlyargcount = kwonlyargcount;
195     co->co_nlocals = nlocals;
196     co->co_stacksize = stacksize;
197     co->co_flags = flags;
198     Py_INCREF(code);
199     co->co_code = code;
200     Py_INCREF(consts);
201     co->co_consts = consts;
202     Py_INCREF(names);
203     co->co_names = names;
204     Py_INCREF(varnames);
205     co->co_varnames = varnames;
206     Py_INCREF(freevars);
207     co->co_freevars = freevars;
208     Py_INCREF(cellvars);
209     co->co_cellvars = cellvars;
210     co->co_cell2arg = cell2arg;
211     Py_INCREF(filename);
212     co->co_filename = filename;
213     Py_INCREF(name);
214     co->co_name = name;
215     co->co_firstlineno = firstlineno;
216     Py_INCREF(lnotab);
217     co->co_lnotab = lnotab;
218     co->co_zombieframe = NULL;
219     co->co_weakreflist = NULL;
220     co->co_extra = NULL;
221     return co;
222 }
223 
224 PyCodeObject *
PyCode_NewEmpty(const char * filename,const char * funcname,int firstlineno)225 PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
226 {
227     static PyObject *emptystring = NULL;
228     static PyObject *nulltuple = NULL;
229     PyObject *filename_ob = NULL;
230     PyObject *funcname_ob = NULL;
231     PyCodeObject *result = NULL;
232     if (emptystring == NULL) {
233         emptystring = PyBytes_FromString("");
234         if (emptystring == NULL)
235             goto failed;
236     }
237     if (nulltuple == NULL) {
238         nulltuple = PyTuple_New(0);
239         if (nulltuple == NULL)
240             goto failed;
241     }
242     funcname_ob = PyUnicode_FromString(funcname);
243     if (funcname_ob == NULL)
244         goto failed;
245     filename_ob = PyUnicode_DecodeFSDefault(filename);
246     if (filename_ob == NULL)
247         goto failed;
248 
249     result = PyCode_New(0,                      /* argcount */
250                 0,                              /* kwonlyargcount */
251                 0,                              /* nlocals */
252                 0,                              /* stacksize */
253                 0,                              /* flags */
254                 emptystring,                    /* code */
255                 nulltuple,                      /* consts */
256                 nulltuple,                      /* names */
257                 nulltuple,                      /* varnames */
258                 nulltuple,                      /* freevars */
259                 nulltuple,                      /* cellvars */
260                 filename_ob,                    /* filename */
261                 funcname_ob,                    /* name */
262                 firstlineno,                    /* firstlineno */
263                 emptystring                     /* lnotab */
264                 );
265 
266 failed:
267     Py_XDECREF(funcname_ob);
268     Py_XDECREF(filename_ob);
269     return result;
270 }
271 
272 #define OFF(x) offsetof(PyCodeObject, x)
273 
274 static PyMemberDef code_memberlist[] = {
275     {"co_argcount",     T_INT,          OFF(co_argcount),       READONLY},
276     {"co_kwonlyargcount",       T_INT,  OFF(co_kwonlyargcount), READONLY},
277     {"co_nlocals",      T_INT,          OFF(co_nlocals),        READONLY},
278     {"co_stacksize",T_INT,              OFF(co_stacksize),      READONLY},
279     {"co_flags",        T_INT,          OFF(co_flags),          READONLY},
280     {"co_code",         T_OBJECT,       OFF(co_code),           READONLY},
281     {"co_consts",       T_OBJECT,       OFF(co_consts),         READONLY},
282     {"co_names",        T_OBJECT,       OFF(co_names),          READONLY},
283     {"co_varnames",     T_OBJECT,       OFF(co_varnames),       READONLY},
284     {"co_freevars",     T_OBJECT,       OFF(co_freevars),       READONLY},
285     {"co_cellvars",     T_OBJECT,       OFF(co_cellvars),       READONLY},
286     {"co_filename",     T_OBJECT,       OFF(co_filename),       READONLY},
287     {"co_name",         T_OBJECT,       OFF(co_name),           READONLY},
288     {"co_firstlineno", T_INT,           OFF(co_firstlineno),    READONLY},
289     {"co_lnotab",       T_OBJECT,       OFF(co_lnotab),         READONLY},
290     {NULL}      /* Sentinel */
291 };
292 
293 /* Helper for code_new: return a shallow copy of a tuple that is
294    guaranteed to contain exact strings, by converting string subclasses
295    to exact strings and complaining if a non-string is found. */
296 static PyObject*
validate_and_copy_tuple(PyObject * tup)297 validate_and_copy_tuple(PyObject *tup)
298 {
299     PyObject *newtuple;
300     PyObject *item;
301     Py_ssize_t i, len;
302 
303     len = PyTuple_GET_SIZE(tup);
304     newtuple = PyTuple_New(len);
305     if (newtuple == NULL)
306         return NULL;
307 
308     for (i = 0; i < len; i++) {
309         item = PyTuple_GET_ITEM(tup, i);
310         if (PyUnicode_CheckExact(item)) {
311             Py_INCREF(item);
312         }
313         else if (!PyUnicode_Check(item)) {
314             PyErr_Format(
315                 PyExc_TypeError,
316                 "name tuples must contain only "
317                 "strings, not '%.500s'",
318                 item->ob_type->tp_name);
319             Py_DECREF(newtuple);
320             return NULL;
321         }
322         else {
323             item = _PyUnicode_Copy(item);
324             if (item == NULL) {
325                 Py_DECREF(newtuple);
326                 return NULL;
327             }
328         }
329         PyTuple_SET_ITEM(newtuple, i, item);
330     }
331 
332     return newtuple;
333 }
334 
335 PyDoc_STRVAR(code_doc,
336 "code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring,\n\
337       constants, names, varnames, filename, name, firstlineno,\n\
338       lnotab[, freevars[, cellvars]])\n\
339 \n\
340 Create a code object.  Not for the faint of heart.");
341 
342 static PyObject *
code_new(PyTypeObject * type,PyObject * args,PyObject * kw)343 code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
344 {
345     int argcount;
346     int kwonlyargcount;
347     int nlocals;
348     int stacksize;
349     int flags;
350     PyObject *co = NULL;
351     PyObject *code;
352     PyObject *consts;
353     PyObject *names, *ournames = NULL;
354     PyObject *varnames, *ourvarnames = NULL;
355     PyObject *freevars = NULL, *ourfreevars = NULL;
356     PyObject *cellvars = NULL, *ourcellvars = NULL;
357     PyObject *filename;
358     PyObject *name;
359     int firstlineno;
360     PyObject *lnotab;
361 
362     if (!PyArg_ParseTuple(args, "iiiiiSO!O!O!UUiS|O!O!:code",
363                           &argcount, &kwonlyargcount,
364                               &nlocals, &stacksize, &flags,
365                           &code,
366                           &PyTuple_Type, &consts,
367                           &PyTuple_Type, &names,
368                           &PyTuple_Type, &varnames,
369                           &filename, &name,
370                           &firstlineno, &lnotab,
371                           &PyTuple_Type, &freevars,
372                           &PyTuple_Type, &cellvars))
373         return NULL;
374 
375     if (argcount < 0) {
376         PyErr_SetString(
377             PyExc_ValueError,
378             "code: argcount must not be negative");
379         goto cleanup;
380     }
381 
382     if (kwonlyargcount < 0) {
383         PyErr_SetString(
384             PyExc_ValueError,
385             "code: kwonlyargcount must not be negative");
386         goto cleanup;
387     }
388     if (nlocals < 0) {
389         PyErr_SetString(
390             PyExc_ValueError,
391             "code: nlocals must not be negative");
392         goto cleanup;
393     }
394 
395     ournames = validate_and_copy_tuple(names);
396     if (ournames == NULL)
397         goto cleanup;
398     ourvarnames = validate_and_copy_tuple(varnames);
399     if (ourvarnames == NULL)
400         goto cleanup;
401     if (freevars)
402         ourfreevars = validate_and_copy_tuple(freevars);
403     else
404         ourfreevars = PyTuple_New(0);
405     if (ourfreevars == NULL)
406         goto cleanup;
407     if (cellvars)
408         ourcellvars = validate_and_copy_tuple(cellvars);
409     else
410         ourcellvars = PyTuple_New(0);
411     if (ourcellvars == NULL)
412         goto cleanup;
413 
414     co = (PyObject *)PyCode_New(argcount, kwonlyargcount,
415                                 nlocals, stacksize, flags,
416                                 code, consts, ournames, ourvarnames,
417                                 ourfreevars, ourcellvars, filename,
418                                 name, firstlineno, lnotab);
419   cleanup:
420     Py_XDECREF(ournames);
421     Py_XDECREF(ourvarnames);
422     Py_XDECREF(ourfreevars);
423     Py_XDECREF(ourcellvars);
424     return co;
425 }
426 
427 static void
code_dealloc(PyCodeObject * co)428 code_dealloc(PyCodeObject *co)
429 {
430     if (co->co_extra != NULL) {
431         PyInterpreterState *interp = PyThreadState_Get()->interp;
432         _PyCodeObjectExtra *co_extra = co->co_extra;
433 
434         for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
435             freefunc free_extra = interp->co_extra_freefuncs[i];
436 
437             if (free_extra != NULL) {
438                 free_extra(co_extra->ce_extras[i]);
439             }
440         }
441 
442         PyMem_Free(co_extra);
443     }
444 
445     Py_XDECREF(co->co_code);
446     Py_XDECREF(co->co_consts);
447     Py_XDECREF(co->co_names);
448     Py_XDECREF(co->co_varnames);
449     Py_XDECREF(co->co_freevars);
450     Py_XDECREF(co->co_cellvars);
451     Py_XDECREF(co->co_filename);
452     Py_XDECREF(co->co_name);
453     Py_XDECREF(co->co_lnotab);
454     if (co->co_cell2arg != NULL)
455         PyMem_FREE(co->co_cell2arg);
456     if (co->co_zombieframe != NULL)
457         PyObject_GC_Del(co->co_zombieframe);
458     if (co->co_weakreflist != NULL)
459         PyObject_ClearWeakRefs((PyObject*)co);
460     PyObject_DEL(co);
461 }
462 
463 static PyObject *
code_sizeof(PyCodeObject * co,void * unused)464 code_sizeof(PyCodeObject *co, void *unused)
465 {
466     Py_ssize_t res = _PyObject_SIZE(Py_TYPE(co));
467     _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) co->co_extra;
468 
469     if (co->co_cell2arg != NULL && co->co_cellvars != NULL) {
470         res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(Py_ssize_t);
471     }
472     if (co_extra != NULL) {
473         res += sizeof(_PyCodeObjectExtra) +
474                (co_extra->ce_size-1) * sizeof(co_extra->ce_extras[0]);
475     }
476     return PyLong_FromSsize_t(res);
477 }
478 
479 static PyObject *
code_repr(PyCodeObject * co)480 code_repr(PyCodeObject *co)
481 {
482     int lineno;
483     if (co->co_firstlineno != 0)
484         lineno = co->co_firstlineno;
485     else
486         lineno = -1;
487     if (co->co_filename && PyUnicode_Check(co->co_filename)) {
488         return PyUnicode_FromFormat(
489             "<code object %U at %p, file \"%U\", line %d>",
490             co->co_name, co, co->co_filename, lineno);
491     } else {
492         return PyUnicode_FromFormat(
493             "<code object %U at %p, file ???, line %d>",
494             co->co_name, co, lineno);
495     }
496 }
497 
498 PyObject*
_PyCode_ConstantKey(PyObject * op)499 _PyCode_ConstantKey(PyObject *op)
500 {
501     PyObject *key;
502 
503     /* Py_None and Py_Ellipsis are singleton */
504     if (op == Py_None || op == Py_Ellipsis
505        || PyLong_CheckExact(op)
506        || PyBool_Check(op)
507        || PyBytes_CheckExact(op)
508        || PyUnicode_CheckExact(op)
509           /* code_richcompare() uses _PyCode_ConstantKey() internally */
510        || PyCode_Check(op)) {
511         key = PyTuple_Pack(2, Py_TYPE(op), op);
512     }
513     else if (PyFloat_CheckExact(op)) {
514         double d = PyFloat_AS_DOUBLE(op);
515         /* all we need is to make the tuple different in either the 0.0
516          * or -0.0 case from all others, just to avoid the "coercion".
517          */
518         if (d == 0.0 && copysign(1.0, d) < 0.0)
519             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
520         else
521             key = PyTuple_Pack(2, Py_TYPE(op), op);
522     }
523     else if (PyComplex_CheckExact(op)) {
524         Py_complex z;
525         int real_negzero, imag_negzero;
526         /* For the complex case we must make complex(x, 0.)
527            different from complex(x, -0.) and complex(0., y)
528            different from complex(-0., y), for any x and y.
529            All four complex zeros must be distinguished.*/
530         z = PyComplex_AsCComplex(op);
531         real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
532         imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
533         /* use True, False and None singleton as tags for the real and imag
534          * sign, to make tuples different */
535         if (real_negzero && imag_negzero) {
536             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_True);
537         }
538         else if (imag_negzero) {
539             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_False);
540         }
541         else if (real_negzero) {
542             key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
543         }
544         else {
545             key = PyTuple_Pack(2, Py_TYPE(op), op);
546         }
547     }
548     else if (PyTuple_CheckExact(op)) {
549         Py_ssize_t i, len;
550         PyObject *tuple;
551 
552         len = PyTuple_GET_SIZE(op);
553         tuple = PyTuple_New(len);
554         if (tuple == NULL)
555             return NULL;
556 
557         for (i=0; i < len; i++) {
558             PyObject *item, *item_key;
559 
560             item = PyTuple_GET_ITEM(op, i);
561             item_key = _PyCode_ConstantKey(item);
562             if (item_key == NULL) {
563                 Py_DECREF(tuple);
564                 return NULL;
565             }
566 
567             PyTuple_SET_ITEM(tuple, i, item_key);
568         }
569 
570         key = PyTuple_Pack(2, tuple, op);
571         Py_DECREF(tuple);
572     }
573     else if (PyFrozenSet_CheckExact(op)) {
574         Py_ssize_t pos = 0;
575         PyObject *item;
576         Py_hash_t hash;
577         Py_ssize_t i, len;
578         PyObject *tuple, *set;
579 
580         len = PySet_GET_SIZE(op);
581         tuple = PyTuple_New(len);
582         if (tuple == NULL)
583             return NULL;
584 
585         i = 0;
586         while (_PySet_NextEntry(op, &pos, &item, &hash)) {
587             PyObject *item_key;
588 
589             item_key = _PyCode_ConstantKey(item);
590             if (item_key == NULL) {
591                 Py_DECREF(tuple);
592                 return NULL;
593             }
594 
595             assert(i < len);
596             PyTuple_SET_ITEM(tuple, i, item_key);
597             i++;
598         }
599         set = PyFrozenSet_New(tuple);
600         Py_DECREF(tuple);
601         if (set == NULL)
602             return NULL;
603 
604         key = PyTuple_Pack(2, set, op);
605         Py_DECREF(set);
606         return key;
607     }
608     else {
609         /* for other types, use the object identifier as a unique identifier
610          * to ensure that they are seen as unequal. */
611         PyObject *obj_id = PyLong_FromVoidPtr(op);
612         if (obj_id == NULL)
613             return NULL;
614 
615         key = PyTuple_Pack(2, obj_id, op);
616         Py_DECREF(obj_id);
617     }
618     return key;
619 }
620 
621 static PyObject *
code_richcompare(PyObject * self,PyObject * other,int op)622 code_richcompare(PyObject *self, PyObject *other, int op)
623 {
624     PyCodeObject *co, *cp;
625     int eq;
626     PyObject *consts1, *consts2;
627     PyObject *res;
628 
629     if ((op != Py_EQ && op != Py_NE) ||
630         !PyCode_Check(self) ||
631         !PyCode_Check(other)) {
632         Py_RETURN_NOTIMPLEMENTED;
633     }
634 
635     co = (PyCodeObject *)self;
636     cp = (PyCodeObject *)other;
637 
638     eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ);
639     if (eq <= 0) goto unequal;
640     eq = co->co_argcount == cp->co_argcount;
641     if (!eq) goto unequal;
642     eq = co->co_kwonlyargcount == cp->co_kwonlyargcount;
643     if (!eq) goto unequal;
644     eq = co->co_nlocals == cp->co_nlocals;
645     if (!eq) goto unequal;
646     eq = co->co_flags == cp->co_flags;
647     if (!eq) goto unequal;
648     eq = co->co_firstlineno == cp->co_firstlineno;
649     if (!eq) goto unequal;
650     eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);
651     if (eq <= 0) goto unequal;
652 
653     /* compare constants */
654     consts1 = _PyCode_ConstantKey(co->co_consts);
655     if (!consts1)
656         return NULL;
657     consts2 = _PyCode_ConstantKey(cp->co_consts);
658     if (!consts2) {
659         Py_DECREF(consts1);
660         return NULL;
661     }
662     eq = PyObject_RichCompareBool(consts1, consts2, Py_EQ);
663     Py_DECREF(consts1);
664     Py_DECREF(consts2);
665     if (eq <= 0) goto unequal;
666 
667     eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);
668     if (eq <= 0) goto unequal;
669     eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);
670     if (eq <= 0) goto unequal;
671     eq = PyObject_RichCompareBool(co->co_freevars, cp->co_freevars, Py_EQ);
672     if (eq <= 0) goto unequal;
673     eq = PyObject_RichCompareBool(co->co_cellvars, cp->co_cellvars, Py_EQ);
674     if (eq <= 0) goto unequal;
675 
676     if (op == Py_EQ)
677         res = Py_True;
678     else
679         res = Py_False;
680     goto done;
681 
682   unequal:
683     if (eq < 0)
684         return NULL;
685     if (op == Py_NE)
686         res = Py_True;
687     else
688         res = Py_False;
689 
690   done:
691     Py_INCREF(res);
692     return res;
693 }
694 
695 static Py_hash_t
code_hash(PyCodeObject * co)696 code_hash(PyCodeObject *co)
697 {
698     Py_hash_t h, h0, h1, h2, h3, h4, h5, h6;
699     h0 = PyObject_Hash(co->co_name);
700     if (h0 == -1) return -1;
701     h1 = PyObject_Hash(co->co_code);
702     if (h1 == -1) return -1;
703     h2 = PyObject_Hash(co->co_consts);
704     if (h2 == -1) return -1;
705     h3 = PyObject_Hash(co->co_names);
706     if (h3 == -1) return -1;
707     h4 = PyObject_Hash(co->co_varnames);
708     if (h4 == -1) return -1;
709     h5 = PyObject_Hash(co->co_freevars);
710     if (h5 == -1) return -1;
711     h6 = PyObject_Hash(co->co_cellvars);
712     if (h6 == -1) return -1;
713     h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
714         co->co_argcount ^ co->co_kwonlyargcount ^
715         co->co_nlocals ^ co->co_flags;
716     if (h == -1) h = -2;
717     return h;
718 }
719 
720 /* XXX code objects need to participate in GC? */
721 
722 static struct PyMethodDef code_methods[] = {
723     {"__sizeof__", (PyCFunction)code_sizeof, METH_NOARGS},
724     {NULL, NULL}                /* sentinel */
725 };
726 
727 PyTypeObject PyCode_Type = {
728     PyVarObject_HEAD_INIT(&PyType_Type, 0)
729     "code",
730     sizeof(PyCodeObject),
731     0,
732     (destructor)code_dealloc,           /* tp_dealloc */
733     0,                                  /* tp_print */
734     0,                                  /* tp_getattr */
735     0,                                  /* tp_setattr */
736     0,                                  /* tp_reserved */
737     (reprfunc)code_repr,                /* tp_repr */
738     0,                                  /* tp_as_number */
739     0,                                  /* tp_as_sequence */
740     0,                                  /* tp_as_mapping */
741     (hashfunc)code_hash,                /* tp_hash */
742     0,                                  /* tp_call */
743     0,                                  /* tp_str */
744     PyObject_GenericGetAttr,            /* tp_getattro */
745     0,                                  /* tp_setattro */
746     0,                                  /* tp_as_buffer */
747     Py_TPFLAGS_DEFAULT,                 /* tp_flags */
748     code_doc,                           /* tp_doc */
749     0,                                  /* tp_traverse */
750     0,                                  /* tp_clear */
751     code_richcompare,                   /* tp_richcompare */
752     offsetof(PyCodeObject, co_weakreflist),     /* tp_weaklistoffset */
753     0,                                  /* tp_iter */
754     0,                                  /* tp_iternext */
755     code_methods,                       /* tp_methods */
756     code_memberlist,                    /* tp_members */
757     0,                                  /* tp_getset */
758     0,                                  /* tp_base */
759     0,                                  /* tp_dict */
760     0,                                  /* tp_descr_get */
761     0,                                  /* tp_descr_set */
762     0,                                  /* tp_dictoffset */
763     0,                                  /* tp_init */
764     0,                                  /* tp_alloc */
765     code_new,                           /* tp_new */
766 };
767 
768 /* Use co_lnotab to compute the line number from a bytecode index, addrq.  See
769    lnotab_notes.txt for the details of the lnotab representation.
770 */
771 
772 int
PyCode_Addr2Line(PyCodeObject * co,int addrq)773 PyCode_Addr2Line(PyCodeObject *co, int addrq)
774 {
775     Py_ssize_t size = PyBytes_Size(co->co_lnotab) / 2;
776     unsigned char *p = (unsigned char*)PyBytes_AsString(co->co_lnotab);
777     int line = co->co_firstlineno;
778     int addr = 0;
779     while (--size >= 0) {
780         addr += *p++;
781         if (addr > addrq)
782             break;
783         line += (signed char)*p;
784         p++;
785     }
786     return line;
787 }
788 
789 /* Update *bounds to describe the first and one-past-the-last instructions in
790    the same line as lasti.  Return the number of that line. */
791 int
_PyCode_CheckLineNumber(PyCodeObject * co,int lasti,PyAddrPair * bounds)792 _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
793 {
794     Py_ssize_t size;
795     int addr, line;
796     unsigned char* p;
797 
798     p = (unsigned char*)PyBytes_AS_STRING(co->co_lnotab);
799     size = PyBytes_GET_SIZE(co->co_lnotab) / 2;
800 
801     addr = 0;
802     line = co->co_firstlineno;
803     assert(line > 0);
804 
805     /* possible optimization: if f->f_lasti == instr_ub
806        (likely to be a common case) then we already know
807        instr_lb -- if we stored the matching value of p
808        somewhere we could skip the first while loop. */
809 
810     /* See lnotab_notes.txt for the description of
811        co_lnotab.  A point to remember: increments to p
812        come in (addr, line) pairs. */
813 
814     bounds->ap_lower = 0;
815     while (size > 0) {
816         if (addr + *p > lasti)
817             break;
818         addr += *p++;
819         if ((signed char)*p)
820             bounds->ap_lower = addr;
821         line += (signed char)*p;
822         p++;
823         --size;
824     }
825 
826     if (size > 0) {
827         while (--size >= 0) {
828             addr += *p++;
829             if ((signed char)*p)
830                 break;
831             p++;
832         }
833         bounds->ap_upper = addr;
834     }
835     else {
836         bounds->ap_upper = INT_MAX;
837     }
838 
839     return line;
840 }
841 
842 
843 int
_PyCode_GetExtra(PyObject * code,Py_ssize_t index,void ** extra)844 _PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
845 {
846     if (!PyCode_Check(code)) {
847         PyErr_BadInternalCall();
848         return -1;
849     }
850 
851     PyCodeObject *o = (PyCodeObject*) code;
852     _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra;
853 
854     if (co_extra == NULL || co_extra->ce_size <= index) {
855         *extra = NULL;
856         return 0;
857     }
858 
859     *extra = co_extra->ce_extras[index];
860     return 0;
861 }
862 
863 
864 int
_PyCode_SetExtra(PyObject * code,Py_ssize_t index,void * extra)865 _PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
866 {
867     PyInterpreterState *interp = PyThreadState_Get()->interp;
868 
869     if (!PyCode_Check(code) || index < 0 ||
870             index >= interp->co_extra_user_count) {
871         PyErr_BadInternalCall();
872         return -1;
873     }
874 
875     PyCodeObject *o = (PyCodeObject*) code;
876     _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra *) o->co_extra;
877 
878     if (co_extra == NULL || co_extra->ce_size <= index) {
879         Py_ssize_t i = (co_extra == NULL ? 0 : co_extra->ce_size);
880         co_extra = PyMem_Realloc(
881                 co_extra,
882                 sizeof(_PyCodeObjectExtra) +
883                 (interp->co_extra_user_count-1) * sizeof(void*));
884         if (co_extra == NULL) {
885             return -1;
886         }
887         for (; i < interp->co_extra_user_count; i++) {
888             co_extra->ce_extras[i] = NULL;
889         }
890         co_extra->ce_size = interp->co_extra_user_count;
891         o->co_extra = co_extra;
892     }
893 
894     if (co_extra->ce_extras[index] != NULL) {
895         freefunc free = interp->co_extra_freefuncs[index];
896         if (free != NULL) {
897             free(co_extra->ce_extras[index]);
898         }
899     }
900 
901     co_extra->ce_extras[index] = extra;
902     return 0;
903 }
904