NAME=pyc load version39
FILE=bins/pyc/py39.pyc
CMDS=<<EOF
iI~machine
EOF
EXPECT=<<EOF
machine  Python 3.9a2 VM (rev Unknown commit)
EOF
RUN

NAME=pyc load version38
FILE=bins/pyc/py38.pyc
CMDS=<<EOF
dr
dr=
EOF
EXPECT=<<EOF
a0 = 0x00000000
a1 = 0x00000000
a2 = 0x00000000
a3 = 0x00000000
r0 = 0x00000000
sp = 0x00000000
pc = 0x00000000
bp = 0x00000000
     a0 0x00000000       a1 0x00000000       a2 0x00000000       a3 0x00000000
     r0 0x00000000       sp 0x00000000       pc 0x00000000       bp 0x00000000
EOF
EXPECT_ERR=
RUN

NAME=pyc malformed refs do not crash
FILE=bins/fuzzed/rep8
CMDS=
EXPECT=
EXPECT_ERR=
RUN

NAME=pyc closing a file frees interned strings once
FILE=bins/pyc/py37.pyc
CMDS=o-*
EXPECT=
EXPECT_ERR=
RUN

NAME=pyc load version38
FILE=bins/pyc/py38.pyc
CMDS=<<EOF
iI~machine
EOF
EXPECT=<<EOF
machine  Python v3.8.0 VM (rev 5d714034866ce1e9f89dc141fe4cc0b50cf20a8e)
EOF
EXPECT_ERR=
RUN

NAME=pyc load version37
FILE=bins/pyc/py37.pyc
CMDS=<<EOF
iI~machine
EOF
EXPECT=<<EOF
machine  Python v3.7.0 VM (rev ae1f6af15f3e4110616801e235873e47fd7d1977)
EOF
EXPECT_ERR=
RUN

NAME=pyc load version36
FILE=bins/pyc/py36.pyc
CMDS=<<EOF
iI~machine
EOF
EXPECT=<<EOF
machine  Python v3.6.0 VM (rev 5c4568a05a0a62b5947c55f68f9f2ecfb90a4f12)
EOF
EXPECT_ERR=
RUN

NAME=pyc load version27
FILE=bins/pyc/py27.pyc
CMDS=<<EOF
iI~machine
EOF
EXPECT=<<EOF
machine  Python 2.7a2 VM (rev edfed0e32cedf3b84c6e999052486a750a3f5bee)
EOF
EXPECT_ERR=
RUN

NAME=pyc symbols
FILE=bins/pyc/py37.pyc
CMDS=<<EOF
is~?Human
EOF
EXPECT=<<EOF
9
EOF
EXPECT_ERR=
RUN

NAME=pyc sections
FILE=bins/pyc/py37.pyc
CMDS=<<EOF
iS~Bat
EOF
EXPECT=<<EOF
30  0x00001f0d   0x2a 0x00001f0d   0x2a -r-x 0x0   ---- <module>.Bat
31  0x00001f5f    0xa 0x00001f5f    0xa -r-x 0x0   ---- <module>.Bat.__init__
32  0x00001fca    0x8 0x00001fca    0x8 -r-x 0x0   ---- <module>.Bat.say
33  0x00002037    0x4 0x00002037    0x4 -r-x 0x0   ---- <module>.Bat.sonar
34  0x00002103   0x1c 0x00002103   0x1c -r-x 0x0   ---- <module>.Batman
35  0x00002143   0x44 0x00002143   0x44 -r-x 0x0   ---- <module>.Batman.__init__
36  0x00002235    0x4 0x00002235    0x4 -r-x 0x0   ---- <module>.Batman.sing
EOF
EXPECT_ERR=
RUN

NAME=pyc entry
FILE=bins/pyc/py37.pyc
CMDS=ie
EXPECT=<<EOF
paddr      vaddr      phaddr     vhaddr     type
------------------------------------------------
0x0000002a 0x0000002a ---------- ---------- program
EOF
EXPECT_ERR=
RUN

NAME=pyc disasm
FILE=bins/pyc/py37.pyc
CMDS=<<EOF
pd 10
EOF
EXPECT=<<EOF
            ;-- section._module_:
            ;-- entry0:
            ;-- <module>:
            0x0000002a      6400           load_const  Multiline strings can be written
    using three "s, and are often used
    as documentation. ; [00] -r-x section size 3218 named <module>
            0x0000002c      5a00           store_name __doc__
            0x0000002e      6401           load_const True
        ,=< 0x00000030      6f0a           jump_if_false_or_pop 10
        |   0x00000032      6402           load_const False
        `-> 0x00000034      0100           pop_top
            0x00000036      6402           load_const False
        ,=< 0x00000038      7012           jump_if_true_or_pop 18
        |   0x0000003a      6401           load_const True
        `-> 0x0000003c      0100           pop_top
EOF
EXPECT_ERR=
RUN

NAME=pyc 37 jumps, extended jumps and extend
FILE=bins/pyc/py37.pyc
CMDS=<<EOF
e io.cache = true
wx 9010 @0x0000002e # make 0x30 extened 0x10
wx 9010 @0x0000002c
pdj 1 @0x00000030~{[0].jump}
pdj 1 @0x0000002e~{[0].jump}
pdj 1 @0x0000002c~{[0].jump}
wx 9010 @0x0000003a
pd2 @0x3a
EOF
EXPECT=<<EOF
52
4148
1052724
            0x0000003a      9010           extended_arg 4096
            0x0000003c      0100           pop_top
EOF
EXPECT_ERR=
RUN

NAME=pyc 38 jumps, extended jumps and extend
FILE=bins/pyc/py38.pyc
CMDS=<<EOF
e io.cache = true
wx 9010 @0x32 # make 0x32 extened 0x10
wx 9010 @0x30
pdj 1 @0x34~{[0].jump}
pdj 1 @0x32~{[0].jump}
pdj 1 @0x30~{[0].jump}
wx 9010 @0x46
pd2 @0x46
EOF
EXPECT=<<EOF
56
4152
1052728
            0x00000046      9010           extended_arg 4096
            0x00000048      0100           pop_top
EOF
EXPECT_ERR=
RUN

NAME=pyc symbols for pyc2.7
FILE=bins/pyc/py27.pyc
CMDS=<<EOF
is~hello_world
EOF
EXPECT=<<EOF
1   0x00000052 0x00000052 NONE FUNC 9        <module>.hello_world
EOF
EXPECT_ERR=
RUN

NAME=pyc disasm for 2.7
FILE=bins/pyc/py27.pyc
CMDS=<<EOF
pd 10
EOF
EXPECT=<<EOF
            ;-- section._module_:
            ;-- entry0:
            ;-- <module>:
            0x0000001e      640000         load_const CodeObject(hello_world) from hello.py ; [00] -r-x section size 25 named <module>
            0x00000021      840000         make_function
            0x00000024      5a0000         store_name hello_world
            0x00000027      640100         load_const 'world'
            0x0000002a      47             print_item
            0x0000002b      48             print_newline
            0x0000002c      650000         load_name hello_world
            0x0000002f      830000         call_function 0 positional, 0 named
            0x00000032      01             pop_top
            0x00000033      640200         load_const None
EOF
EXPECT_ERR=
RUN

NAME=pyc code objects made of TYPE_REF to code objects
FILE=malloc://718
CMDS=<<EOF
wx 550d0d0a000000000000000000000000630000000000000000000000000000000000000000000000007304000000640053002809000000e30000000000000000000000000000000000000000000000004e4e4e4e4e4e4e4e010000004ee300000000000000000000000000000000000000000000000072000000007200000000720000000072000000007200000000720000000072000000007200000000010000007200000000e300000000000000000000000000000000000000000000000072010000007201000000720100000072010000007201000000720100000072010000007201000000010000007201000000e300000000000000000000000000000000000000000000000072020000007202000000720200000072020000007202000000720200000072020000007202000000010000007202000000e300000000000000000000000000000000000000000000000072030000007203000000720300000072030000007203000000720300000072030000007203000000010000007203000000e300000000000000000000000000000000000000000000000072040000007204000000720400000072040000007204000000720400000072040000007204000000010000007204000000e300000000000000000000000000000000000000000000000072050000007205000000720500000072050000007205000000720500000072050000007205000000010000007205000000e300000000000000000000000000000000000000000000000072060000007206000000720600000072060000007206000000720600000072060000007206000000010000007206000000e30000000000000000000000000000000000000000000000007207000000720700000072070000007207000000720700000072070000007207000000720700000001000000720700000029002900290029007a04612e70797a083c6d6f64756c653e010000007300000000
oba 0
is~module
EOF
EXPECT=<<EOF
0   0x0000002e 0x0000002e NONE FUNC 4        <module>
EOF
RUN

NAME=pyc consts tuples made of TYPE_REF to code objects
FILE=malloc://1003
CMDS=<<EOF
wx 550d0d0a000000000000000000000000630000000000000000000000000000000000000000000000007304000000640053002809000000e3000000000000000000000000000000000000000000000000730400000064005300290029002900290029007a01667a0167010000007300000000e3000000000000000000000000000000000000000000000000730400000064005300280900000072000000007200000000720000000072000000007200000000720000000072000000007200000000720000000029002900290029007a01667a0167010000007300000000e3000000000000000000000000000000000000000000000000730400000064005300280900000072010000007201000000720100000072010000007201000000720100000072010000007201000000720100000029002900290029007a01667a0167010000007300000000e3000000000000000000000000000000000000000000000000730400000064005300280900000072020000007202000000720200000072020000007202000000720200000072020000007202000000720200000029002900290029007a01667a0167010000007300000000e3000000000000000000000000000000000000000000000000730400000064005300280900000072030000007203000000720300000072030000007203000000720300000072030000007203000000720300000029002900290029007a01667a0167010000007300000000e3000000000000000000000000000000000000000000000000730400000064005300280900000072040000007204000000720400000072040000007204000000720400000072040000007204000000720400000029002900290029007a01667a0167010000007300000000e3000000000000000000000000000000000000000000000000730400000064005300280900000072050000007205000000720500000072050000007205000000720500000072050000007205000000720500000029002900290029007a01667a0167010000007300000000e3000000000000000000000000000000000000000000000000730400000064005300280900000072060000007206000000720600000072060000007206000000720600000072060000007206000000720600000029002900290029007a01667a0167010000007300000000e3000000000000000000000000000000000000000000000000730400000064005300280900000072070000007207000000720700000072070000007207000000720700000072070000007207000000720700000029002900290029007a01667a016701000000730000000029002900290029007a04612e70797a083c6d6f64756c653e010000007300000000
oba 0
isq~?
iSq~?
EOF
EXPECT=<<EOF
10
10
EOF
RUN

NAME=pyc function
FILE=bins/pyc/py27.pyc
CMDS=<<EOF
af
pdf
EOF
EXPECT=<<EOF
            ;-- section._module_:
            ;-- <module>:
/ 25: entry0 ();
|           0x0000001e      640000         load_const CodeObject(hello_world) from hello.py ; [00] -r-x section size 25 named <module>
|           0x00000021      840000         make_function
|           0x00000024      5a0000         store_name hello_world
|           0x00000027      640100         load_const 'world'
|           0x0000002a      47             print_item
|           0x0000002b      48             print_newline
|           0x0000002c      650000         load_name hello_world
|           0x0000002f      830000         call_function 0 positional, 0 named
|           0x00000032      01             pop_top
|           0x00000033      640200         load_const None
\           0x00000036      53             return_value
EOF
EXPECT_ERR=
RUN

NAME=pyc dict constant prints its items, not the list pointer
FILE=hex://03f30d0a00000000630000000000000000010000004000000073040000006400005328010000007b4e4e3028000000002800000000280000000028000000007304000000612e707973080000003c6d6f64756c653e010000007300000000
CMDS=pi 2
EXPECT=<<EOF
load_const (None,None)
return_value
EOF
RUN

NAME=pyc non-string name operand
FILE=hex://550d0d0a0000000000000000000000006300000000000000000000000000000000010000004000000073040000006500530029014e2901532900290029007a04782e70797a0166010000007300000000
CMDS=pi 2
EXPECT=<<EOF
load_name
return_value
EOF
RUN

NAME=pyc nested code object without a name
FILE=hex://03f30d0a00000000630000000000000000010000004000000073040000006400005328010000006300000000000000000100000040000000730100000053280000000028000000002800000000280000000028000000007304000000612e70793001000000730000000028000000002800000000280000000028000000007304000000612e707973080000003c6d6f64756c653e010000007300000000
CMDS=pi 2
EXPECT=<<EOF
load_const CodeObject() from a.py
return_value
EOF
RUN

NAME=pyc colored name ending in $
FILE=hex://550d0d0a0000000000000000000000006300000000000000000000000000000000010000004000000073040000006500530029014e29017a0261242900290029007a04782e70797a0166010000007300000000
CMDS=<<EOF
e scr.color=1
pi 1
EOF
EXPECT=<<EOF
[35m[35m[35mload_name[37m a[32m[32m$[0m[0m
EOF
RUN

NAME=pyc opcode table follows asm.cpu changes
FILE=bins/pyc/py39.pyc
CMDS=<<EOF2
pi 1 @ entry0+2
e asm.cpu=v2.7.0
pi 1 @ entry0+2
e asm.cpu=3.9a2
pi 1 @ entry0+2
EOF2
EXPECT=<<EOF2
store_name __doc__
store_name
store_name __doc__
EOF2
RUN

NAME=pyc nested code objects sharing a long name
FILE=malloc://382
CMDS=<<EOF
wx 994e0d0a000000006300000000000000007301000000532902f3c8000000414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414163000000000000000073010000005329016300000000000000007301000000532901630000000000000000730100000053290263000000000000000073010000005329004e4e4e720000000001004e63000000000000000073010000005329004e4e4e720000000001004e4e4e4e720000000001004e4e4e4e720000000001004e4e4e4e720000000001004e4e4e4e73010000006d01004e
oba 0
?l `isq~:0[2]`
?l `isq~:1[2]`
?l `isq~:2[2]`
?l `isq~:3[2]`
?l `isq~:5[2]`
?l `iSq~:3[3]`
EOF
EXPECT=<<EOF
1
202
403
512
512
512
EOF
RUN

NAME=pyc string length larger than the file is rejected without allocating it
FILE=bins/pyc/string-length-past-eof.pyc
CMDS=<<EOF
iI~arch
iS
EOF
EXPECT=<<EOF
arch     pyc
nth paddr       size vaddr       vsize perm flags type name
-----------------------------------------------------------
0   0x0000002e   0x2 0x0000002e    0x2 -r-x 0x0   ---- main
EOF
RUN

NAME=pyc complex length larger than the file is rejected without allocating it
FILE=bins/pyc/complex-length-past-eof.pyc
CMDS=<<EOF
iI~arch
iS
EOF
EXPECT=<<EOF
arch     pyc
nth paddr       size vaddr       vsize perm flags type name
-----------------------------------------------------------
0   0x0000001e   0x2 0x0000001e    0x2 -r-x 0x0   ---- main
EOF
RUN

NAME=pyc code object with argcount 65535 bounds the recovered vm args
FILE=hex://550d0d0a000000000000000000000000e3ffff0000000000000000000000000000010000004000000073040000006400530029014e29002900290029007a04612e70797a083c6d6f64756c653e010000007300000000
TIMEOUT=30
CMDS=<<EOF
af
afl~?
afv~?
afvr~l255$
afvr~l256$
EOF
EXPECT=<<EOF
1
256
arg int l255 @ l255
EOF
RUN
