-
-
Notifications
You must be signed in to change notification settings - Fork 54
ast27 gives syntax error for valid code on s390x #151
Comments
I’m as stumped as you. Does ast27 parse this on other platforms? |
Yes, for example on x86_64: >>> from typed_ast import ast27
>>> ast27.parse('''#!/usr/bin/env python2.7
...
... def function((_globals, _locals)):
... print _globals, _locals
... ''')
<typed_ast._ast27.Module object at 0x7f23004190d0> |
Related: #139 (comment) It's interesting that it passes on Python 2.7.18. Diffing the two ast.c's and looking through the changes in |
Maybe it's an endianness problem? IIUC s390 is big-endian, while most prevailing architectures (certainly x86) are little-endian. This would be tough to track down without access to the hardware, so I think the OP will have to debug their own problem. :-( |
Well this is rather bizzare. I got somewhat nerd sniped by this problem and initially tried running s390x in QEMU, but I couldn't get Linux to boot correctly, so I gave up (suffice to say it isn't the most supported platform out there). I then tried on an old powerbook g4, which uses powerpc and thus is also big endian (though it is only 32bit). I tried running things and everything worked correctly, both the example shown here and all the tests passed unlike #139. So either this is not specific to BE, or its only 64bit BE. |
Thanks for trying that! I believe we have some copies of header files that are used to describe internal APIs. Maybe those are slightly out of sync in a way that only becomes a problem on BE64? FWIW This may just be a duplicate of #139, as @hauntsaninja pointed out. @Ikke, are you interested in digging in? |
Can't seem to repro here. (It's the PASE Python build shipped by IBM for i, FWIW.)
|
Sure, though I do need some pointers on how to debug python extensions, which I do not have experience with. I have python installed with debug symbols, and also built |
I would start by finding how the error message is generated, e.g. by grepping for "can't assign to". It's possible that this message is constructed out of pieces, maybe grep for "assign to". |
Thanks, I tried something like that before, but could not find anything. Now I found the set_context function that most likely returns this error. Specifically this code: case Tuple_kind:
if (asdl_seq_LEN(e->v.Tuple.elts)) {
e->v.Tuple.ctx = ctx;
s = e->v.Tuple.elts;
}
else {
expr_name = "()";
}
break;
#define asdl_seq_LEN(S) ((S) == NULL ? 0 : (S)->size) So I guess we need to confirm whether |
I suppose you could put a breakpoint there and get a traceback from gdb so you can tell where it's called from. |
Yes, was working on that. This is what I found so far: (gdb) p *e.v.Tuple.elts
$2 = {size = 0, elements = {0x2aa000b26d8}}
(gdb) bt
#0 set_context (c=c@entry=0x3ffffffe920, e=e@entry=0x2aa000b2748, ctx=ctx@entry=Store, n=n@entry=0x3fffdafb198) at ast27/Python/ast.c:459
#1 0x000003fffda92546 in compiler_complex_args (c=c@entry=0x3ffffffe920, n=n@entry=0x3fffdafb198) at ast27/Python/ast.c:726
#2 0x000003fffda93224 in ast_for_arguments (c=c@entry=0x3ffffffe920, n=<optimized out>) at ast27/Python/ast.c:823
#3 0x000003fffda9838c in ast_for_funcdef (c=c@entry=0x3ffffffe920, n=0x3fffdacf8d0, decorator_seq=decorator_seq@entry=0x0) at ast27/Python/ast.c:1022
#4 0x000003fffda96350 in ast_for_stmt (c=c@entry=0x3ffffffe920, n=<optimized out>, n@entry=0x3fffdafb3f0) at ast27/Python/ast.c:3493
#5 0x000003fffda98db6 in Ta27AST_FromNode (n=n@entry=0x3fffdacf810, flags=flags@entry=0x3ffffffea30, filename=<optimized out>, arena=arena@entry=0x3fffdba5af0) at ast27/Python/ast.c:275
#6 0x000003fffdaacb1a in string_object_to_c_ast (arena=0x3fffdba5af0, flags=0x3ffffffea30, start=257, filename=0x3fffdad2a30,
s=0x3fffdb95210 "#!/usr/bin/env python2.7\n\ndef function((_globals, _locals)):\n print _globals, _locals\n") at ast27/Custom/typed_ast.c:226
#7 string_object_to_py_ast (flags=0x3ffffffea30, start=<optimized out>, filename=0x3fffdad2a30, str=0x3fffdb95210 "#!/usr/bin/env python2.7\n\ndef function((_globals, _locals)):\n print _globals, _locals\n")
at ast27/Custom/typed_ast.c:248
#8 ast27_parse_impl (mode=<optimized out>, filename=0x3fffdad2a30, source=<optimized out>) at ast27/Custom/typed_ast.c:291
#9 ast27_parse (self=<optimized out>, args=<optimized out>) at ast27/Custom/typed_ast.c:312
#10 0x000003fffdcd0c30 in cfunction_call_varargs (func=0x3fffdac2630, args=0x3fffdaf3f40, kwargs=0x0) at Objects/call.c:757
[..]
|
Yup, compiler_complex_args is what's responsible for tuple parameter unpacking (as I alluded to in #151 (comment)). I'd just step through it on both architectures and see where they differ. Maybe |
You should probably turn off optimizations in the compiler so you don't get the FWIW I worry that what you're seeing in this traceback is just the code producing the error message, which maybe removed from the actual parsing problem that's the root cause. |
I've added
Yes, I figured as much, so I would need to find where this part of the AST is generated. |
I'd look into |
Not sure if it means something, but one difference I found: I found something peculiar: In compiler_complex_args, a new If I step through with gdb in s390x, on line 685: (gdb) p *args
$14 = {size = 0, elements = {0x0}}
(gdb) n So Same on x86_64: (gdb) p *args
$5 = {size = 2, elements = {0x0}} Here, The peculiar thing, if I check the value of size right before it's returned from (gdb) p *seq
$10 = {size = 2, elements = {0x0}} So here it's still 2, but right after it returns, it suddenly 0. Note that for some reason, it looks for But the fact that size is 0 in that |
Interesting: (gdb) x/16xb args
0x2aa000b26c0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02
0x2aa000b26c8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 So the size is still present in the data For comparrson, on x86_64: (gdb) x/16hb args
0x7ffff7ad1240: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7ffff7ad1248: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 For looking at the assembly, I would need a bit more guidance, I have no experience with that (though, I can probably defer it other with more experience on s390x, but I don't know when they have time). |
Nice! Okay, so to confirm, on S390X, when the same memory is interpreted as Maybe |
Bingo: in asdl.c:
in ast.c: (gdb) ptype asdl_seq
type = struct {
int size;
void *elements[1];
} So |
Yay! That explains @ethanhs ' findings as well. Edit: |
Yes, it does. I also ran the black test suite, which passes now. Thanks! |
Hooray! Thank you for debugging (and reporting)! @gvanrossum would you be willing to review #152 and maybe make a release? |
Fixes #151 and fixes #139 Linking shenanigans caused ast27 to link against Python's asdl.c, instead of ast27/Python/asdl.c. Python's asdl.c uses Py_ssize_t for asdl_seq's size whereas ast27/Python/asdl.c uses int. This means we were interpreting memory differently in asdl.c and ast.c. On 64-bit big-endian systems, this caused us to misplace asdl.c's writes to asdl_seq->size, since Py_ssize_t is eight bytes, but int is four. The fix mirrors what we do in ast3, that is, manually namespace definitions to avoid linking conflicts. Co-authored-by: hauntsaninja <>
Release made: https://pypi.org/project/typed-ast/1.4.2/
Please test!
|
This examples comes from the test suite of black
Results in:
The same code parses fine on python 2.7.18.
This is with typed-ast 1.4.1. It only happens on s390x on Alpine Linux edge.
Let me know if you need more information.
The text was updated successfully, but these errors were encountered: