• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "Python.h"
2 #include "code.h"
3 #include "structmember.h"
4 
5 #define NAME_CHARS \
6     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
7 
8 /* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
9 
10 static int
all_name_chars(unsigned char * s)11 all_name_chars(unsigned char *s)
12 {
13     static char ok_name_char[256];
14     static unsigned char *name_chars = (unsigned char *)NAME_CHARS;
15 
16     if (ok_name_char[*name_chars] == 0) {
17         unsigned char *p;
18         for (p = name_chars; *p; p++)
19             ok_name_char[*p] = 1;
20     }
21     while (*s) {
22         if (ok_name_char[*s++] == 0)
23             return 0;
24     }
25     return 1;
26 }
27 
28 static void
intern_strings(PyObject * tuple)29 intern_strings(PyObject *tuple)
30 {
31     Py_ssize_t i;
32 
33     for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
34         PyObject *v = PyTuple_GET_ITEM(tuple, i);
35         if (v == NULL || !PyString_CheckExact(v)) {
36             Py_FatalError("non-string found in code slot");
37         }
38         PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
39     }
40 }
41 
42 
43 PyCodeObject *
PyCode_New(int argcount,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)44 PyCode_New(int argcount, int nlocals, int stacksize, int flags,
45            PyObject *code, PyObject *consts, PyObject *names,
46            PyObject *varnames, PyObject *freevars, PyObject *cellvars,
47            PyObject *filename, PyObject *name, int firstlineno,
48            PyObject *lnotab)
49 {
50     PyCodeObject *co;
51     Py_ssize_t i;
52     /* Check argument types */
53     if (argcount < 0 || nlocals < 0 ||
54         code == NULL ||
55         consts == NULL || !PyTuple_Check(consts) ||
56         names == NULL || !PyTuple_Check(names) ||
57         varnames == NULL || !PyTuple_Check(varnames) ||
58         freevars == NULL || !PyTuple_Check(freevars) ||
59         cellvars == NULL || !PyTuple_Check(cellvars) ||
60         name == NULL || !PyString_Check(name) ||
61         filename == NULL || !PyString_Check(filename) ||
62         lnotab == NULL || !PyString_Check(lnotab) ||
63         !PyObject_CheckReadBuffer(code)) {
64         PyErr_BadInternalCall();
65         return NULL;
66     }
67     intern_strings(names);
68     intern_strings(varnames);
69     intern_strings(freevars);
70     intern_strings(cellvars);
71     /* Intern selected string constants */
72     for (i = PyTuple_Size(consts); --i >= 0; ) {
73         PyObject *v = PyTuple_GetItem(consts, i);
74         if (!PyString_Check(v))
75             continue;
76         if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))
77             continue;
78         PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));
79     }
80     co = PyObject_NEW(PyCodeObject, &PyCode_Type);
81     if (co != NULL) {
82         co->co_argcount = argcount;
83         co->co_nlocals = nlocals;
84         co->co_stacksize = stacksize;
85         co->co_flags = flags;
86         Py_INCREF(code);
87         co->co_code = code;
88         Py_INCREF(consts);
89         co->co_consts = consts;
90         Py_INCREF(names);
91         co->co_names = names;
92         Py_INCREF(varnames);
93         co->co_varnames = varnames;
94         Py_INCREF(freevars);
95         co->co_freevars = freevars;
96         Py_INCREF(cellvars);
97         co->co_cellvars = cellvars;
98         Py_INCREF(filename);
99         co->co_filename = filename;
100         Py_INCREF(name);
101         co->co_name = name;
102         co->co_firstlineno = firstlineno;
103         Py_INCREF(lnotab);
104         co->co_lnotab = lnotab;
105         co->co_zombieframe = NULL;
106         co->co_weakreflist = NULL;
107     }
108     return co;
109 }
110 
111 PyCodeObject *
PyCode_NewEmpty(const char * filename,const char * funcname,int firstlineno)112 PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
113 {
114     static PyObject *emptystring = NULL;
115     static PyObject *nulltuple = NULL;
116     PyObject *filename_ob = NULL;
117     PyObject *funcname_ob = NULL;
118     PyCodeObject *result = NULL;
119     if (emptystring == NULL) {
120         emptystring = PyString_FromString("");
121         if (emptystring == NULL)
122             goto failed;
123     }
124     if (nulltuple == NULL) {
125         nulltuple = PyTuple_New(0);
126         if (nulltuple == NULL)
127             goto failed;
128     }
129     funcname_ob = PyString_FromString(funcname);
130     if (funcname_ob == NULL)
131         goto failed;
132     filename_ob = PyString_FromString(filename);
133     if (filename_ob == NULL)
134         goto failed;
135 
136     result = PyCode_New(0,                      /* argcount */
137                 0,                              /* nlocals */
138                 0,                              /* stacksize */
139                 0,                              /* flags */
140                 emptystring,                    /* code */
141                 nulltuple,                      /* consts */
142                 nulltuple,                      /* names */
143                 nulltuple,                      /* varnames */
144                 nulltuple,                      /* freevars */
145                 nulltuple,                      /* cellvars */
146                 filename_ob,                    /* filename */
147                 funcname_ob,                    /* name */
148                 firstlineno,                    /* firstlineno */
149                 emptystring                     /* lnotab */
150                 );
151 
152 failed:
153     Py_XDECREF(funcname_ob);
154     Py_XDECREF(filename_ob);
155     return result;
156 }
157 
158 #define OFF(x) offsetof(PyCodeObject, x)
159 
160 static PyMemberDef code_memberlist[] = {
161     {"co_argcount",     T_INT,          OFF(co_argcount),       READONLY},
162     {"co_nlocals",      T_INT,          OFF(co_nlocals),        READONLY},
163     {"co_stacksize",T_INT,              OFF(co_stacksize),      READONLY},
164     {"co_flags",        T_INT,          OFF(co_flags),          READONLY},
165     {"co_code",         T_OBJECT,       OFF(co_code),           READONLY},
166     {"co_consts",       T_OBJECT,       OFF(co_consts),         READONLY},
167     {"co_names",        T_OBJECT,       OFF(co_names),          READONLY},
168     {"co_varnames",     T_OBJECT,       OFF(co_varnames),       READONLY},
169     {"co_freevars",     T_OBJECT,       OFF(co_freevars),       READONLY},
170     {"co_cellvars",     T_OBJECT,       OFF(co_cellvars),       READONLY},
171     {"co_filename",     T_OBJECT,       OFF(co_filename),       READONLY},
172     {"co_name",         T_OBJECT,       OFF(co_name),           READONLY},
173     {"co_firstlineno", T_INT,           OFF(co_firstlineno),    READONLY},
174     {"co_lnotab",       T_OBJECT,       OFF(co_lnotab),         READONLY},
175     {NULL}      /* Sentinel */
176 };
177 
178 /* Helper for code_new: return a shallow copy of a tuple that is
179    guaranteed to contain exact strings, by converting string subclasses
180    to exact strings and complaining if a non-string is found. */
181 static PyObject*
validate_and_copy_tuple(PyObject * tup)182 validate_and_copy_tuple(PyObject *tup)
183 {
184     PyObject *newtuple;
185     PyObject *item;
186     Py_ssize_t i, len;
187 
188     len = PyTuple_GET_SIZE(tup);
189     newtuple = PyTuple_New(len);
190     if (newtuple == NULL)
191         return NULL;
192 
193     for (i = 0; i < len; i++) {
194         item = PyTuple_GET_ITEM(tup, i);
195         if (PyString_CheckExact(item)) {
196             Py_INCREF(item);
197         }
198         else if (!PyString_Check(item)) {
199             PyErr_Format(
200                 PyExc_TypeError,
201                 "name tuples must contain only "
202                 "strings, not '%.500s'",
203                 item->ob_type->tp_name);
204             Py_DECREF(newtuple);
205             return NULL;
206         }
207         else {
208             item = PyString_FromStringAndSize(
209                 PyString_AS_STRING(item),
210                 PyString_GET_SIZE(item));
211             if (item == NULL) {
212                 Py_DECREF(newtuple);
213                 return NULL;
214             }
215         }
216         PyTuple_SET_ITEM(newtuple, i, item);
217     }
218 
219     return newtuple;
220 }
221 
222 PyDoc_STRVAR(code_doc,
223 "code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\
224       varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\
225 \n\
226 Create a code object.  Not for the faint of heart.");
227 
228 static PyObject *
code_new(PyTypeObject * type,PyObject * args,PyObject * kw)229 code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
230 {
231     int argcount;
232     int nlocals;
233     int stacksize;
234     int flags;
235     PyObject *co = NULL;
236     PyObject *code;
237     PyObject *consts;
238     PyObject *names, *ournames = NULL;
239     PyObject *varnames, *ourvarnames = NULL;
240     PyObject *freevars = NULL, *ourfreevars = NULL;
241     PyObject *cellvars = NULL, *ourcellvars = NULL;
242     PyObject *filename;
243     PyObject *name;
244     int firstlineno;
245     PyObject *lnotab;
246 
247     if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
248                           &argcount, &nlocals, &stacksize, &flags,
249                           &code,
250                           &PyTuple_Type, &consts,
251                           &PyTuple_Type, &names,
252                           &PyTuple_Type, &varnames,
253                           &filename, &name,
254                           &firstlineno, &lnotab,
255                           &PyTuple_Type, &freevars,
256                           &PyTuple_Type, &cellvars))
257         return NULL;
258 
259     if (argcount < 0) {
260         PyErr_SetString(
261             PyExc_ValueError,
262             "code: argcount must not be negative");
263         goto cleanup;
264     }
265 
266     if (nlocals < 0) {
267         PyErr_SetString(
268             PyExc_ValueError,
269             "code: nlocals must not be negative");
270         goto cleanup;
271     }
272 
273     ournames = validate_and_copy_tuple(names);
274     if (ournames == NULL)
275         goto cleanup;
276     ourvarnames = validate_and_copy_tuple(varnames);
277     if (ourvarnames == NULL)
278         goto cleanup;
279     if (freevars)
280         ourfreevars = validate_and_copy_tuple(freevars);
281     else
282         ourfreevars = PyTuple_New(0);
283     if (ourfreevars == NULL)
284         goto cleanup;
285     if (cellvars)
286         ourcellvars = validate_and_copy_tuple(cellvars);
287     else
288         ourcellvars = PyTuple_New(0);
289     if (ourcellvars == NULL)
290         goto cleanup;
291 
292     co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,
293                                 code, consts, ournames, ourvarnames,
294                                 ourfreevars, ourcellvars, filename,
295                                 name, firstlineno, lnotab);
296   cleanup:
297     Py_XDECREF(ournames);
298     Py_XDECREF(ourvarnames);
299     Py_XDECREF(ourfreevars);
300     Py_XDECREF(ourcellvars);
301     return co;
302 }
303 
304 static void
code_dealloc(PyCodeObject * co)305 code_dealloc(PyCodeObject *co)
306 {
307     Py_XDECREF(co->co_code);
308     Py_XDECREF(co->co_consts);
309     Py_XDECREF(co->co_names);
310     Py_XDECREF(co->co_varnames);
311     Py_XDECREF(co->co_freevars);
312     Py_XDECREF(co->co_cellvars);
313     Py_XDECREF(co->co_filename);
314     Py_XDECREF(co->co_name);
315     Py_XDECREF(co->co_lnotab);
316     if (co->co_zombieframe != NULL)
317         PyObject_GC_Del(co->co_zombieframe);
318     if (co->co_weakreflist != NULL)
319         PyObject_ClearWeakRefs((PyObject*)co);
320     PyObject_DEL(co);
321 }
322 
323 static PyObject *
code_repr(PyCodeObject * co)324 code_repr(PyCodeObject *co)
325 {
326     char buf[500];
327     int lineno = -1;
328     char *filename = "???";
329     char *name = "???";
330 
331     if (co->co_firstlineno != 0)
332         lineno = co->co_firstlineno;
333     if (co->co_filename && PyString_Check(co->co_filename))
334         filename = PyString_AS_STRING(co->co_filename);
335     if (co->co_name && PyString_Check(co->co_name))
336         name = PyString_AS_STRING(co->co_name);
337     PyOS_snprintf(buf, sizeof(buf),
338                   "<code object %.100s at %p, file \"%.300s\", line %d>",
339                   name, co, filename, lineno);
340     return PyString_FromString(buf);
341 }
342 
343 static int
code_compare(PyCodeObject * co,PyCodeObject * cp)344 code_compare(PyCodeObject *co, PyCodeObject *cp)
345 {
346     int cmp;
347     cmp = PyObject_Compare(co->co_name, cp->co_name);
348     if (cmp) return cmp;
349     cmp = co->co_argcount - cp->co_argcount;
350     if (cmp) goto normalize;
351     cmp = co->co_nlocals - cp->co_nlocals;
352     if (cmp) goto normalize;
353     cmp = co->co_flags - cp->co_flags;
354     if (cmp) goto normalize;
355     cmp = co->co_firstlineno - cp->co_firstlineno;
356     if (cmp) goto normalize;
357     cmp = PyObject_Compare(co->co_code, cp->co_code);
358     if (cmp) return cmp;
359     cmp = PyObject_Compare(co->co_consts, cp->co_consts);
360     if (cmp) return cmp;
361     cmp = PyObject_Compare(co->co_names, cp->co_names);
362     if (cmp) return cmp;
363     cmp = PyObject_Compare(co->co_varnames, cp->co_varnames);
364     if (cmp) return cmp;
365     cmp = PyObject_Compare(co->co_freevars, cp->co_freevars);
366     if (cmp) return cmp;
367     cmp = PyObject_Compare(co->co_cellvars, cp->co_cellvars);
368     return cmp;
369 
370  normalize:
371     if (cmp > 0)
372         return 1;
373     else if (cmp < 0)
374         return -1;
375     else
376         return 0;
377 }
378 
379 static PyObject *
code_richcompare(PyObject * self,PyObject * other,int op)380 code_richcompare(PyObject *self, PyObject *other, int op)
381 {
382     PyCodeObject *co, *cp;
383     int eq;
384     PyObject *res;
385 
386     if ((op != Py_EQ && op != Py_NE) ||
387         !PyCode_Check(self) ||
388         !PyCode_Check(other)) {
389 
390         /* Py3K warning if types are not equal and comparison
391         isn't == or !=  */
392         if (PyErr_WarnPy3k("code inequality comparisons not supported "
393                            "in 3.x", 1) < 0) {
394             return NULL;
395         }
396 
397         Py_INCREF(Py_NotImplemented);
398         return Py_NotImplemented;
399     }
400 
401     co = (PyCodeObject *)self;
402     cp = (PyCodeObject *)other;
403 
404     eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ);
405     if (eq <= 0) goto unequal;
406     eq = co->co_argcount == cp->co_argcount;
407     if (!eq) goto unequal;
408     eq = co->co_nlocals == cp->co_nlocals;
409     if (!eq) goto unequal;
410     eq = co->co_flags == cp->co_flags;
411     if (!eq) goto unequal;
412     eq = co->co_firstlineno == cp->co_firstlineno;
413     if (!eq) goto unequal;
414     eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);
415     if (eq <= 0) goto unequal;
416     eq = PyObject_RichCompareBool(co->co_consts, cp->co_consts, Py_EQ);
417     if (eq <= 0) goto unequal;
418     eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);
419     if (eq <= 0) goto unequal;
420     eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);
421     if (eq <= 0) goto unequal;
422     eq = PyObject_RichCompareBool(co->co_freevars, cp->co_freevars, Py_EQ);
423     if (eq <= 0) goto unequal;
424     eq = PyObject_RichCompareBool(co->co_cellvars, cp->co_cellvars, Py_EQ);
425     if (eq <= 0) goto unequal;
426 
427     if (op == Py_EQ)
428         res = Py_True;
429     else
430         res = Py_False;
431     goto done;
432 
433   unequal:
434     if (eq < 0)
435         return NULL;
436     if (op == Py_NE)
437         res = Py_True;
438     else
439         res = Py_False;
440 
441   done:
442     Py_INCREF(res);
443     return res;
444 }
445 
446 static long
code_hash(PyCodeObject * co)447 code_hash(PyCodeObject *co)
448 {
449     long h, h0, h1, h2, h3, h4, h5, h6;
450     h0 = PyObject_Hash(co->co_name);
451     if (h0 == -1) return -1;
452     h1 = PyObject_Hash(co->co_code);
453     if (h1 == -1) return -1;
454     h2 = PyObject_Hash(co->co_consts);
455     if (h2 == -1) return -1;
456     h3 = PyObject_Hash(co->co_names);
457     if (h3 == -1) return -1;
458     h4 = PyObject_Hash(co->co_varnames);
459     if (h4 == -1) return -1;
460     h5 = PyObject_Hash(co->co_freevars);
461     if (h5 == -1) return -1;
462     h6 = PyObject_Hash(co->co_cellvars);
463     if (h6 == -1) return -1;
464     h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
465         co->co_argcount ^ co->co_nlocals ^ co->co_flags;
466     if (h == -1) h = -2;
467     return h;
468 }
469 
470 /* XXX code objects need to participate in GC? */
471 
472 PyTypeObject PyCode_Type = {
473     PyVarObject_HEAD_INIT(&PyType_Type, 0)
474     "code",
475     sizeof(PyCodeObject),
476     0,
477     (destructor)code_dealloc,           /* tp_dealloc */
478     0,                                  /* tp_print */
479     0,                                  /* tp_getattr */
480     0,                                  /* tp_setattr */
481     (cmpfunc)code_compare,              /* tp_compare */
482     (reprfunc)code_repr,                /* tp_repr */
483     0,                                  /* tp_as_number */
484     0,                                  /* tp_as_sequence */
485     0,                                  /* tp_as_mapping */
486     (hashfunc)code_hash,                /* tp_hash */
487     0,                                  /* tp_call */
488     0,                                  /* tp_str */
489     PyObject_GenericGetAttr,            /* tp_getattro */
490     0,                                  /* tp_setattro */
491     0,                                  /* tp_as_buffer */
492     Py_TPFLAGS_DEFAULT,                 /* tp_flags */
493     code_doc,                           /* tp_doc */
494     0,                                  /* tp_traverse */
495     0,                                  /* tp_clear */
496     code_richcompare,                   /* tp_richcompare */
497     offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */
498     0,                                  /* tp_iter */
499     0,                                  /* tp_iternext */
500     0,                                  /* tp_methods */
501     code_memberlist,                    /* tp_members */
502     0,                                  /* tp_getset */
503     0,                                  /* tp_base */
504     0,                                  /* tp_dict */
505     0,                                  /* tp_descr_get */
506     0,                                  /* tp_descr_set */
507     0,                                  /* tp_dictoffset */
508     0,                                  /* tp_init */
509     0,                                  /* tp_alloc */
510     code_new,                           /* tp_new */
511 };
512 
513 /* Use co_lnotab to compute the line number from a bytecode index, addrq.  See
514    lnotab_notes.txt for the details of the lnotab representation.
515 */
516 
517 int
PyCode_Addr2Line(PyCodeObject * co,int addrq)518 PyCode_Addr2Line(PyCodeObject *co, int addrq)
519 {
520     int size = PyString_Size(co->co_lnotab) / 2;
521     unsigned char *p = (unsigned char*)PyString_AsString(co->co_lnotab);
522     int line = co->co_firstlineno;
523     int addr = 0;
524     while (--size >= 0) {
525         addr += *p++;
526         if (addr > addrq)
527             break;
528         line += *p++;
529     }
530     return line;
531 }
532 
533 /* Update *bounds to describe the first and one-past-the-last instructions in
534    the same line as lasti.  Return the number of that line. */
535 int
_PyCode_CheckLineNumber(PyCodeObject * co,int lasti,PyAddrPair * bounds)536 _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
537 {
538     int size, addr, line;
539     unsigned char* p;
540 
541     p = (unsigned char*)PyString_AS_STRING(co->co_lnotab);
542     size = PyString_GET_SIZE(co->co_lnotab) / 2;
543 
544     addr = 0;
545     line = co->co_firstlineno;
546     assert(line > 0);
547 
548     /* possible optimization: if f->f_lasti == instr_ub
549        (likely to be a common case) then we already know
550        instr_lb -- if we stored the matching value of p
551        somwhere we could skip the first while loop. */
552 
553     /* See lnotab_notes.txt for the description of
554        co_lnotab.  A point to remember: increments to p
555        come in (addr, line) pairs. */
556 
557     bounds->ap_lower = 0;
558     while (size > 0) {
559         if (addr + *p > lasti)
560             break;
561         addr += *p++;
562         if (*p)
563             bounds->ap_lower = addr;
564         line += *p++;
565         --size;
566     }
567 
568     if (size > 0) {
569         while (--size >= 0) {
570             addr += *p++;
571             if (*p++)
572                 break;
573         }
574         bounds->ap_upper = addr;
575     }
576     else {
577         bounds->ap_upper = INT_MAX;
578     }
579 
580     return line;
581 }
582