From 4d81a16638a857572cc482cb97b25be3decb2896 Mon Sep 17 00:00:00 2001 From: TheHellTower <119943599+TheHellTower@users.noreply.github.com> Date: Wed, 1 Mar 2023 00:48:33 +0100 Subject: [PATCH] Add `PUSH_NULL`, `PRECALL_A`, `CALL_A` support (#324) * Add `PUSH_NULL`, `PRECALL_A`, `CALL_A` support * feat: @zrax Co-authored-by: Michael Hansen * Good suggested change to make the code shorter * Add `PUSH_NULL`, `PRECALL`, `CALL` test tokenized * Add `PUSH_NULL`, `PRECALL`, `CALL` test * Add `PUSH_NULL`, `PRECALL`, `CALL` test compiled * Delete push_null-precall-call.3.11.pyc * Delete push_null-precall-call.py * Delete push_null-precall-call.txt * Update README.markdown Blank commit to re-run the tests. * Join all no-ops/"fake"-ops together * Update ASTree.cpp https://github.com/zrax/pycdc/pull/324#issuecomment-1449049283 * Add compiled test for #324 --------- Co-authored-by: Michael Hansen --- ASTree.cpp | 24 +++++++++++++++--------- tests/compiled/test_calls.3.11.pyc | Bin 0 -> 585 bytes 2 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 tests/compiled/test_calls.3.11.pyc diff --git a/ASTree.cpp b/ASTree.cpp index 7af32d9..3122a94 100644 --- a/ASTree.cpp +++ b/ASTree.cpp @@ -474,6 +474,7 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) stack.push(new ASTTuple(values)); } break; + case Pyc::CALL_A: case Pyc::CALL_FUNCTION_A: { int kwparams = (operand & 0xFF00) >> 8; @@ -540,12 +541,16 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) pparamList.push_front(decor_name); } - } else { + } + else { pparamList.push_front(param); } } PycRef func = stack.top(); stack.pop(); + if (opcode == Pyc::CALL_A && stack.top() == nullptr) + stack.pop(); + stack.push(new ASTCall(func, pparamList, kwparamList)); } break; @@ -1032,12 +1037,6 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) stack.push(new ASTAwaitable(object)); } break; - case Pyc::GET_ITER: - /* We just entirely ignore this */ - break; - case Pyc::GET_YIELD_FROM_ITER: - /* We just entirely ignore this */ - break; case Pyc::IMPORT_NAME_A: if (mod->majorVer() == 1) { stack.push(new ASTImport(new ASTName(code->getName(operand)), NULL)); @@ -2547,14 +2546,21 @@ PycRef BuildFromCode(PycRef code, PycModule* mod) case Pyc::SETUP_ANNOTATIONS: variable_annotations = true; break; + case Pyc::GET_ITER: + case Pyc::GET_YIELD_FROM_ITER: + break; + case Pyc::PRECALL_A: + case Pyc::RESUME_A: + /* We just entirely ignore this / no-op */ + break; case Pyc::CACHE: /* These "fake" opcodes are used as placeholders for optimizing certain opcodes in Python 3.11+. Since we have no need for that during disassembly/decompilation, we can just treat these as no-ops. */ break; - case Pyc::RESUME_A: - /* Treated as no-op for decompyle purposes */ + case Pyc::PUSH_NULL: + stack.push(nullptr); break; default: fprintf(stderr, "Unsupported opcode: %s\n", Pyc::OpcodeName(opcode & 0xFF)); diff --git a/tests/compiled/test_calls.3.11.pyc b/tests/compiled/test_calls.3.11.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09cb36fecc4e62025798baecc44be7656ac1a855 GIT binary patch literal 585 zcmah_O-sW-5S`6uO)0iQQA-cK))tHC!Grh{yr`F6Bz7aF#3UrC(t?meK)s0w_1IHI z`ezy`81_`~~`-8b`QX5a2Ur&1D7yB5D{cNE{lBsSqE7&8c<0~j#U zpgKiVMGDlJxV6j1(L7?NM<@GqO%1{SGYYD6aetSOqj|(E=6Y1QKU4p$!hj-R{x6nR zL@X>;7Bd9lbdL)5XQGI{{1A%bN5~ws_#?%3B*LB<24PQSYl5Vfuv6G5Y;6}4gtePC zVGNrHwu6m^L-;F8briyxvU5(jx}oZXH!W3n2&Y`i+6#=sV<+nlJ=LzLy4i3lVSG}P zHO<~Mo0G)eg@GHIvTtQ*XZW4=4c$IjgirvI8+iarZsa3iJ?Rb7uaLf9^C35c+yHXH z9J}(k+Q~oUpOo&gpD7J9B_GN|C=Z}K0^a3a+)jE)HyKP57vJu-bx-#pJA~{2vJu}F MJ<*NaTBdjT26@eQP5=M^ literal 0 HcmV?d00001