Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5b72218

Browse files
committed
* Fixed some subtleties with fastlocals. You can no longer access
f_fastlocals in a traceback object (this is a core dump hazard if there are <nil> entries), but instead eval_code() merges the fast locals back into the locals dictionary if it looks like the local variables will be retained. Also, the merge routines save exceptions since this is sometimes needed (alas!). * Added id() to bltinmodule.c, which returns an object's address (identity). Useful to walk arbitrary data structures containing cycles. * Added compile() to bltinmodule.c and compile_string() to pythonrun.[ch]: support to exec/eval arbitrary code objects. The code that defaults globals and locals is moved from run_node in pythonrun.c (which is now identical to eval_node) to eval_code in ceval.c. [XXX For elegance a clean-up session is necessary.]
1 parent 8b17d6b commit 5b72218

5 files changed

Lines changed: 117 additions & 36 deletions

File tree

Include/pythonrun.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ object *run_file PROTO((FILE *, char *, int, object *, object *));
4242
object *run_err_node PROTO((int, struct _node *, char *, object *, object *));
4343
object *run_node PROTO((struct _node *, char *, object *, object *));
4444

45+
object *compile_string PROTO((char *, char *, int));
46+
4547
void print_error PROTO((void));
4648

4749
void goaway PROTO((int));

Objects/frameobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ static struct memberlist frame_memberlist[] = {
3838
{"f_code", T_OBJECT, OFF(f_code)},
3939
{"f_globals", T_OBJECT, OFF(f_globals)},
4040
{"f_locals", T_OBJECT, OFF(f_locals)},
41-
{"f_fastlocals",T_OBJECT, OFF(f_fastlocals)},
41+
/* {"f_fastlocals",T_OBJECT, OFF(f_fastlocals)}, /* XXX Unsafe */
4242
{"f_localmap", T_OBJECT, OFF(f_localmap)},
4343
{"f_lasti", T_INT, OFF(f_lasti)},
4444
{"f_lineno", T_INT, OFF(f_lineno)},

Python/bltinmodule.c

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3535
#include "pythonrun.h"
3636
#include "ceval.h"
3737
#include "modsupport.h"
38+
#include "compile.h"
39+
#include "eval.h"
3840

3941
static object *
4042
builtin_abs(self, v)
@@ -106,6 +108,29 @@ builtin_coerce(self, args)
106108
return res;
107109
}
108110

111+
static object *
112+
builtin_compile(self, args)
113+
object *self;
114+
object *args;
115+
{
116+
char *str;
117+
char *filename;
118+
char *startstr;
119+
int start;
120+
if (!getargs(args, "(sss)", &str, &filename, &startstr))
121+
return NULL;
122+
if (strcmp(startstr, "exec") == 0)
123+
start = file_input;
124+
else if (strcmp(startstr, "eval") == 0)
125+
start = eval_input;
126+
else {
127+
err_setstr(ValueError,
128+
"compile() mode must be 'exec' or 'eval'");
129+
return NULL;
130+
}
131+
return compile_string(str, filename, start);
132+
}
133+
109134
static object *
110135
builtin_dir(self, v)
111136
object *self;
@@ -168,23 +193,26 @@ exec_eval(v, start)
168193
char *s;
169194
int n;
170195
if (v != NULL) {
171-
if (is_stringobject(v))
172-
str = v;
173-
else if (is_tupleobject(v) &&
196+
if (is_tupleobject(v) &&
174197
((n = gettuplesize(v)) == 2 || n == 3)) {
175198
str = gettupleitem(v, 0);
176199
globals = gettupleitem(v, 1);
177200
if (n == 3)
178201
locals = gettupleitem(v, 2);
179202
}
203+
else
204+
str = v;
180205
}
181-
if (str == NULL || !is_stringobject(str) ||
206+
if (str == NULL || (!is_stringobject(str) && !is_codeobject(str)) ||
182207
globals != NULL && !is_dictobject(globals) ||
183208
locals != NULL && !is_dictobject(locals)) {
184209
err_setstr(TypeError,
185-
"exec/eval arguments must be string[,dict[,dict]]");
210+
"exec/eval arguments must be (string|code)[,dict[,dict]]");
186211
return NULL;
187212
}
213+
if (is_codeobject(str))
214+
return eval_code((codeobject *) str, globals, locals,
215+
(object *)NULL);
188216
s = getstringvalue(str);
189217
if (strlen(s) != getstringsize(str)) {
190218
err_setstr(ValueError, "embedded '\\0' in string arg");
@@ -305,6 +333,17 @@ builtin_hasattr(self, args)
305333
return newintobject(1L);
306334
}
307335

336+
static object *
337+
builtin_id(self, args)
338+
object *self;
339+
object *args;
340+
{
341+
object *v;
342+
if (!getargs(args, "O", &v))
343+
return NULL;
344+
return newintobject((long)v);
345+
}
346+
308347
static object *
309348
builtin_setattr(self, args)
310349
object *self;
@@ -713,6 +752,7 @@ static struct methodlist builtin_methods[] = {
713752
{"chr", builtin_chr},
714753
{"cmp", builtin_cmp},
715754
{"coerce", builtin_coerce},
755+
{"compile", builtin_compile},
716756
{"dir", builtin_dir},
717757
{"divmod", builtin_divmod},
718758
{"eval", builtin_eval},
@@ -723,6 +763,7 @@ static struct methodlist builtin_methods[] = {
723763
{"hasattr", builtin_hasattr},
724764
{"hash", builtin_hash},
725765
{"hex", builtin_hex},
766+
{"id", builtin_id},
726767
{"input", builtin_input},
727768
{"int", builtin_int},
728769
{"len", builtin_len},

Python/ceval.c

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4545
#define CHECKEXC 1 /* Double-check exception checking */
4646
#endif
4747

48+
#define DEBUG
49+
50+
4851
/* Forward declarations */
4952

5053
#ifdef LLTRACE
@@ -82,6 +85,7 @@ static object *cmp_outcome PROTO((int, object *, object *));
8285
static int import_from PROTO((object *, object *, object *));
8386
static object *build_class PROTO((object *, object *));
8487
static void locals_2_fast PROTO((frameobject *, int));
88+
static void fast_2_locals PROTO((frameobject *));
8589

8690

8791
/* Pointer to current frame, used to link new frames to */
@@ -178,6 +182,7 @@ eval_code(co, globals, locals, arg)
178182
object *trace = NULL; /* Trace function or NULL */
179183
object *retval; /* Return value iff why == WHY_RETURN */
180184
char *name; /* Name used by some instructions */
185+
int needmerge = 0;
181186
#ifdef LLTRACE
182187
int lltrace = dictlookup(globals, "__lltrace__") != NULL;
183188
#endif
@@ -217,6 +222,18 @@ eval_code(co, globals, locals, arg)
217222
#define POP() BASIC_POP()
218223
#endif
219224

225+
if (globals == NULL) {
226+
globals = getglobals();
227+
if (locals == NULL) {
228+
locals = getlocals();
229+
needmerge = 1;
230+
}
231+
}
232+
else {
233+
if (locals == NULL)
234+
locals = globals;
235+
}
236+
220237
f = newframeobject(
221238
current_frame, /*back*/
222239
co, /*code*/
@@ -1328,11 +1345,17 @@ eval_code(co, globals, locals, arg)
13281345
why = WHY_EXCEPTION;
13291346
}
13301347
}
1348+
1349+
if (fastlocals && (f->ob_refcnt > 1 || f->f_locals->ob_refcnt > 2))
1350+
fast_2_locals(f);
13311351

13321352
/* Restore previous frame and release the current one */
13331353

13341354
current_frame = f->f_back;
13351355
DECREF(f);
1356+
1357+
if (needmerge)
1358+
locals_2_fast(current_frame, 1);
13361359

13371360
return retval;
13381361
}
@@ -1417,7 +1440,9 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
14171440
INCREF(arg);
14181441
settupleitem(arglist, 2, arg);
14191442
tracing++;
1443+
fast_2_locals(f);
14201444
res = call_object(*p_trace, arglist);
1445+
locals_2_fast(f, 1);
14211446
tracing--;
14221447
cleanup:
14231448
XDECREF(arglist);
@@ -1447,24 +1472,25 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
14471472
}
14481473
}
14491474

1450-
object *
1451-
getlocals()
1452-
{
1453-
/* Merge f->f_fastlocals into f->f_locals, then return the latter */
1475+
static void
1476+
fast_2_locals(f)
14541477
frameobject *f;
1478+
{
1479+
/* Merge f->f_fastlocals into f->f_locals */
14551480
object *locals, *fast, *map;
1481+
object *error_type, *error_value;
14561482
int i;
1457-
f = current_frame;
14581483
if (f == NULL)
1459-
return NULL;
1484+
return;
14601485
locals = f->f_locals;
14611486
fast = f->f_fastlocals;
14621487
map = f->f_localmap;
14631488
if (locals == NULL || fast == NULL || map == NULL)
1464-
return locals;
1489+
return;
14651490
if (!is_dictobject(locals) || !is_listobject(fast) ||
14661491
!is_dictobject(map))
1467-
return locals;
1492+
return;
1493+
err_get(&error_type, &error_value);
14681494
i = getdictsize(map);
14691495
while (--i >= 0) {
14701496
object *key;
@@ -1488,7 +1514,7 @@ getlocals()
14881514
err_clear();
14891515
}
14901516
}
1491-
return locals;
1517+
err_setval(error_type, error_value);
14921518
}
14931519

14941520
static void
@@ -1538,6 +1564,15 @@ mergelocals()
15381564
locals_2_fast(current_frame, 1);
15391565
}
15401566

1567+
object *
1568+
getlocals()
1569+
{
1570+
if (current_frame == NULL)
1571+
return NULL;
1572+
fast_2_locals(current_frame);
1573+
return current_frame->f_locals;
1574+
}
1575+
15411576
object *
15421577
getglobals()
15431578
{

Python/pythonrun.c

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ object *
263263
run_string(str, start, globals, locals)
264264
char *str;
265265
int start;
266-
/*dict*/object *globals, *locals;
266+
object *globals, *locals;
267267
{
268268
node *n;
269269
int err;
@@ -276,7 +276,7 @@ run_file(fp, filename, start, globals, locals)
276276
FILE *fp;
277277
char *filename;
278278
int start;
279-
/*dict*/object *globals, *locals;
279+
object *globals, *locals;
280280
{
281281
node *n;
282282
int err;
@@ -289,7 +289,7 @@ run_err_node(err, n, filename, globals, locals)
289289
int err;
290290
node *n;
291291
char *filename;
292-
/*dict*/object *globals, *locals;
292+
object *globals, *locals;
293293
{
294294
if (err != E_DONE) {
295295
err_input(err);
@@ -302,25 +302,9 @@ object *
302302
run_node(n, filename, globals, locals)
303303
node *n;
304304
char *filename;
305-
/*dict*/object *globals, *locals;
305+
object *globals, *locals;
306306
{
307-
object *res;
308-
int needmerge = 0;
309-
if (globals == NULL) {
310-
globals = getglobals();
311-
if (locals == NULL) {
312-
locals = getlocals();
313-
needmerge = 1;
314-
}
315-
}
316-
else {
317-
if (locals == NULL)
318-
locals = globals;
319-
}
320-
res = eval_node(n, filename, globals, locals);
321-
if (needmerge)
322-
mergelocals();
323-
return res;
307+
return eval_node(n, filename, globals, locals);
324308
}
325309

326310
object *
@@ -341,6 +325,25 @@ eval_node(n, filename, globals, locals)
341325
return v;
342326
}
343327

328+
object *
329+
compile_string(str, filename, start)
330+
char *str;
331+
char *filename;
332+
int start;
333+
{
334+
node *n;
335+
int err;
336+
codeobject *co;
337+
err = parse_string(str, start, &n);
338+
if (err != E_DONE) {
339+
err_input(err);
340+
return NULL;
341+
}
342+
co = compile(n, filename);
343+
freetree(n);
344+
return (object *)co;
345+
}
346+
344347
/* Simplified interface to parsefile */
345348

346349
int

0 commit comments

Comments
 (0)