#esoteric-python
1 messages · Page 15 of 1
no, i can't, getting only Skiddie kid, idk what i am missing https://paste.pythondiscord.com/muqefexawe
@dry mirage can einspect put a non hashable object into a set
asking for a friend
specifically i want to make a self referential set
my friend*
idk about einspect but fishhook can

how 
adding a hash method onto the target class (or object) would work i guess
!e
import fishhook
@fishhook.hook(set)
def __hash__(self):
return 0
x = set()
x.add(x)
print(x)
@languid hare :white_check_mark: Your 3.11 eval job has completed with return code 0.
{set(...)}
hmm
I haven't implemented the backend struct for PySetObject yet
but brb 👀
from ctypes import pointer
from einspect.structs import PyObject
from einspect.structs.py_set import PySetObject, SetEntry
s = set()
item = [1, 2, 3]
obj = PySetObject.from_object(s)
obj.smalltable[0] = SetEntry(key=pointer(PyObject.from_object(item)), hash=123)
obj.fill += 1
obj.used += 1
print(s)
>> {[1, 2, 3]}
obj.smalltable[1] = SetEntry(key=pointer(PyObject.from_object(s)), hash=456)
obj.fill += 1
obj.used += 1
print(s)
>> {[1, 2, 3], set(...)}
haven't made the SetView yet but this will be the struct implementation
damn
does accessing work 
like what access 
print(s.pop())
print(s.pop())
does membership testing work 
well...
__contains__ tries to hash the list, so it'll fail there with TypeError
sad but expected
Afternoon all,
Has anybody been working with the signature inspection by any chance?
I wonder what your thoughts are on the following:
from inspect import signature
def something(arg1: date):
...
sig = signature(something)
for p in sig.parameters.values():
print(p.annotation.__class__)
I have not tested the above, just simplified from my code. But the challenge I have is that the class represented there should return a date argument, but in fact return a string.
Am I doing something wrong?
h
#type-hinting may be helpful depending on your use case, but in a nutshell you should use typing.get_type_hints() if you want forward references to be evaluated
Thanks @earnest wing.
How would you do a a check to verify the compatibility between the signature in a method and a given argument passed at a run-time?
So far I was introspecting, and parsing the signature, then verifying what sort of type(arg) was given.
I can't use the isinstance as I might have a data type not declared in my generic method file.
I tried, without success, to store a reference to the original data type. Since this approach didn't work, when I parse the signaure I store the data type in a string format
I tried, without success, to store a reference to the original data type
why didn't it work/what about it didnt work
if you can get the local and global namespace the function is defined in you should be fine
first, check locals for the type
if can't find it there, check the globals
if can't find there, check builtins
It didn't work for a couple of reasons:
a) mostly ignorance, as I wasn't sure how to do it
b) but looking at all the methods available in the signature class, none of them is returning the "reference" to the class ... all is always a string
if you can get the namespace the function is defined in, you can use the string to get the class reference
func.__module__ and func.__qualname__ will get you the namespace as a string
so if you parse that then you can get the classes from the strings
So parsing is the best approach I have
I'll give it a try later. Thanks for the hint
np, im happy to help out
Hello @versed eagle not sure what's the time your end ... I did try the func bits above, but they return me the module name where the function is stored rather than the proper class of the argument I'm inspecting.
Am I missing something from your suggestion?
f"{func.__module__}.{func.__qualname__}" is the namespace where the function is
using the string that you already have, you can get the type from the namespace
import secrets,marshal
def Pingu(message: str):
xstrip = ''
xstrip += str(len(message)*50-5^1)
for letter in message.strip():
xstrip += str(ord(letter))
xstrip += bin(int(ord(letter)))
CPILE = compile(f"""har_{xstrip} = None""", secrets.token_hex(), 'single').co_code
CPILE_FOL = marshal.dumps(CPILE).hex()
return CPILE_FOL.upper()
print(Pingu('hello'))
Is this a kinda good hashing function
No, that would be constant
The co_code for that should always be a LOAD_CONST 0, STORE_NAME, 0, LOAD_CONST, 0, RETURN
Or something equivalent
!e ```py
import secrets,marshal
def Pingu(message: str):
xstrip = ''
xstrip += str(len(message)*50-5^1)
for letter in message.strip():
xstrip += str(ord(letter))
xstrip += bin(int(ord(letter)))
CPILE = compile(f"""har_{xstrip} = None""", secrets.token_hex(), 'single').co_code
CPILE_FOL = marshal.dumps(CPILE).hex()
return CPILE_FOL.upper()
print(Pingu('hello'))
print(Pingu('goodbye'))
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | F30A000000970064005A0064005300
002 | F30A000000970064005A0064005300
@sick hound ^
any way to golf this further
for i in sys.argv[1:]:j=str(Fraction(i));print(j+("/"not in j)*"/1")```
!e ```py
from types import CodeType
exec(CodeType(
0, 0, 0, 0, 30, 0, b"\x97\x00\x02\x00e\x00d\x00\xa6\x01\x00\x00\xab\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00d\x01S\x00", ("Hi", None), ("print",), (), "", "", "", 0, b"", b""
))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hi
istg
?
!e
from types import CodeType
exec(CodeType(
0, 0, 0, 0, 30, 0, b"\x97\x00\x02\x00e\x00d\x00\xa6\x01\x00\x00\xab\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00d\x01S\x00", ("Hellooo", None), ("print",), (), "", "", "", 0, b"", b""
))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hellooo
Wait how is this like?
whats the bytes for?
i mean like its clear on what it does ("Hellooo", None), ("print",), (),
so whats the point
welcome to the wonderful world of python bytecode
Yeah
ok
first tuple are consts, second are names
the bytecode specifies what to do with the consts and names
Yeah but why? would you need that.
python does it all the time behind the scenes
ever noticed __pycache__?
Yeah
thats cached bytecode from your .py source files
cpython does all the pythoning in bytecode, your source code is just compiled before its executed
ahhhh
!e ```py
from types import CodeType
import dis
dis.dis(CodeType(
0, 0, 0, 0, 30, 0, b"\x97\x00\x02\x00e\x00d\x00\xa6\x01\x00\x00\xab\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00d\x01S\x00", ("Hi", None), ("print",), (), "", "", "", 0, b"", b""
))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0 RESUME 0
002 | 2 PUSH_NULL
003 | 4 LOAD_NAME 0 (print)
004 | 6 LOAD_CONST 0 ('Hi')
005 | 8 PRECALL 1
006 | 12 CALL 1
007 | 22 POP_TOP
008 | 24 LOAD_CONST 1 (None)
009 | 26 RETURN_VALUE
here's how the disassembly of that looks like
Yeah ive seen pythons dis lib.
I was just saying whats the point of doing it like that
like print() seems simpler
funny
oh it is
but why do it the simple way when you can do this

this is esoteric python afterall

no but really, if you want to do fucked up shit like generating a class without using class:
here you go
inline assembly
assembly 💀
well thats what it is
not actual assembly assembly
but python assembly
i see
ile take a look at that
one line for statements
I'm trying to one line the entire mandelbrot #python-discussion message
I only got to 8
I tried to use it but it gave me no output
[((z:=i) if i < 5 else None) if i < 10 else None for i in range(10 + 1)]
On phone so can't write up a proper example, but I use them in this one line program of mine py (pg:=__import__("pygame"),__import__("pygame.locals"),ri:=__import__("random").randint,sc:=pg.display.set_mode((600, 600)),cl:=pg.time.Clock(),sp:=pg.Vector2(10,10),sb:=[],di:=pg.Vector2(10,0),nf:=lambda:globals().update(fo=pg.Vector2(ri(0,59)*10,ri(0,59)*10)),nf(),[(sb.append(pg.Vector2(sp)),sb.pop(0),sp.__iadd__(di),(sb.clear(),sp.update(10,10))if(sp in sb or not(0<=sp.x<=600and 0<=sp.y<=600))else None,(sb.insert(0,pg.Vector2(-10,-10)),nf())if sp==fo else None,sc.fill((0,0,0)),pg.draw.rect(sc,(255,0,0),(fo.x,fo.y,10,10)),pg.draw.rect(sc,(255,255,255),(sp.x,sp.y,10,10)),[pg.draw.rect(sc,(255,255,255),(p.x,p.y,10,10))for p in sb],[((1/0)if ev.type==pg.locals.QUIT else di.update({pg.locals.K_w:(0,-10),pg.locals.K_s:(0,10),pg.locals.K_a:(-10,0),pg.locals.K_d:(10,0)}.get(ev.key,di))if ev.type==pg.locals.KEYDOWN else None)for ev in pg.event.get()],pg.display.update(),cl.tick(10),)for _ in iter(int,1)])
wghat the hell
It's snake!
holy hell
and it is not even golfed to the max (notice the 2 char variable names)
ye
I use lists instead of tuples for doing one line
vivax how do you one line for statements with a break condition inside of it?
example of what I mean
for i in range(10):
# do smth
if i == 5: break
For loops get tricky to do breaks in, you would need to raise an exception then catch it
So best is really to try and avoid the need, like if it is to exit a program you can instead crash it with 1/0
[((SOME CODE) if CONDITION else None) if i < MAX_I else CODE AFTER STATEMENT for i in range(MAX_I + 1)]
I use this but it does not work on my program
it works on testing
but just doesn't work when I actually use it
[((z:=complex(z*z+c)) if abs(z) > 2 else None) if i<M else (print("#" if i+1 == M else ".", end="\n" if x+1 == W else "")) for i in range(M+1)]
this is how I used it on my actual code
I forgor
for i in range(M):
z = z*z+c
if abs(z) > 2: break
print("#" if i+1 == M else ".", end="\n" if x+1 == W else "")
unobfuscated version
Shouldn't that work? Let me double check something
no it didnt
lemme show you
everything is the max iteration (9)
it shoulkd look like this
the numbers represent how much iteration it had passed without breaking out
isnt that abs condition the wrong way around?
it should break on abs(z) > 2, but currently that is the only time it executes the loop body
ye
the else None is very slow because it waits until the final iteration and not actually break
is there any alternative to this?
([(z:=complex(z*z+c))for i,_ in zip(range(M+1), iter(lambda: abs(z) > 2, True))], print("#" if i+1 == M else ".", end="\n" if x+1 == W else ""))
this maybe
that should stop when the condition is True
syntax error 👀
ops
there edited
so we basically use iter(lambda: BREAK_CONDITION, True) as a form of while loop, then use zip to combine it with the range (and zip will stop when one of them runs out)
oh shoot, comprehensions dont leak that do they
I am not sure what the best way of solving that is, I guess you could bind i to another name in the loop body
or we could do [... for globals()["i"],_ in zip(...)]
I'm starting to not understand
basically comprehensions have their own scope for the iteration variables (in this case i) meaning after the comprehension ends it is not saved
you could also just define it each iteration, should be simpler
okay
OH SHIT
it formed the mandelbrot contours
it workkedd omgggg
5 lines to go
thank you
heres the image it formed
nice!
np 😄
I amm so happy right now
[W:=64,H:=32,M:=128,[[[r:=(x-W/2)*4/W-1,I:=(y-H/2)*4/H,c:=r+complex(0,I),z:=complex(0,0), ([(z:=complex(z*z+c),e:=i)for i,_ in zip(range(M+1), iter(lambda: abs(z) > 2, True))], print("#" if e == M else ".", end="\n" if x+1 == W else ""))] for x in range(W)] for y in range(H)]]
finally, mandelbrot in 1 line of code
!e
[W:=64,H:=32,M:=128,[[[r:=(x-W/2)*4/W-1,I:=(y-H/2)*4/H,c:=r+complex(0,I),z:=complex(0,0), ([(z:=complex(z*z+c),e:=i)for i,_ in zip(range(M+1), iter(lambda: abs(z) > 2, True))], print("#" if e == M else ".", end="\n" if x+1 == W else ""))] for x in range(W)] for y in range(H)]]
@manic flax :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | ................................................................
002 | ................................................................
003 | ................................................................
004 | ................................................................
005 | ................................................................
006 | ................................................................
007 | ................................................................
008 | ................................................................
009 | ................................................#...............
010 | ..............................................#.................
011 | .............................................###................
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/unotijefov.txt?noredirect
lol
golf
170 ```py
M=128
for y in range(H:=32):
for x in range(W:=64):c=(x-W/2)4/W-1+(y-H/2)4/H1j;z=0j;print(end=".#"[len([z:=zz+c for i in range(M+1)if abs(z)<3])==M+1]+"\n"*(x+1==W))
165 ```py
M=128
for y in range(H:=32):
for x in range(W:=64):c=(x-W/2)4/W-1+(y-H/2)4/H1j;z=0j;print(end=".#"[len([z:=zz+c for i in range(M+1)if abs(z)<3])==M+1])
print()
162 ```py
M=128;W=64
for y in range(H:=32):x=0;exec('z=c=(x-W/2)4/W-1+(y-H/2)4/H1j;print(end=".#"[len([z:=zz+c for i in range(M+1)if abs(z)<3])==M+1]);x+=1;'*W);print()
157 ```py
M=128;W=64
for y in range(H:=32):x=0;exec('z=0;print(end=".#"[len([i for i in range(M+1)if abs(z:=z*z+(x-W/2)*4/W-1+(y-H/2)4/H1j)<3])>M]);x+=1;'*W);print()
can't all the W/2 and 4/W stuff be replaced with just their numerical values to reduce characters
we're allowing those values to be customizable
ah
but i mean if we're just gonna stick to those values might as well just do it
also replace (x-W/2)*4/W-1 with x*4/W-3?
also probably same thing with the y bit
Use 129 for M and put -~ in front of abs?
Nvm I misread the listcomp
I think you can get rid of the [] in len()
do you think a generator comprehension has a length?
len doesn't work on generators?
no
Ah
anyways 146 ```py
M=128;W=64
for y in range(H:=32):x=0;exec('z=0;print(end=".#"[len([i for i in range(M+1)if abs(z:=zz+x4/W-3+4j/H*y-2j)<3])>M]);x+=1;'*W);print()
probably because you'd have to iterate over the entire generator to find the length
example of how to obfuscate something like "import sys"
hardcoded version 134 ```py
for y in range(32):x=0;exec('z=0;print(end=".#"[len([i for i in range(129)if abs(z:=zz+x/16-3+y1j/8-2j)<3])>128]);x+=1;'*64);print()
(_____________________:=(__:=__builtins__.__getattribute__((___:=__name__.__class__.__doc__.__getitem__((___________:=(______:=(___:=__name__.__getitem__((_____:=__name__.__class__().__len__()))).__add__(___).__add__(___).__len__()).__mul__((________:=(_______:=(___:=__name__.__getitem__(_____)).__add__(___).__len__()).__mul__(_______).__add__(______))).__add__((__________:=_______.__mul__((_________:=_______.__mul__(_______).__invert__().__neg__())))))).__add__(__name__.__class__.__doc__.__getitem__(___________)).__add__(__name__.__len__().__class__.__doc__.__getitem__(_____)).__add__((______________:=(______________:=__name__.__ne__(__name__).__invert__()).__neg__().__truediv__(______________.__add__(______________).__neg__()).__rpow__(______________).__class__).__name__.__getitem__(_______)).__add__(__name__.__class__.__class__.__doc__.__getitem__(_______)).__add__((________________:=__name__.__class__.__base__).__name__.__getitem__(_____)).__add__(______________.__doc__.__getitem__((__________________:=__name__.__eq__(__name__).__pos__()))).__add__(__name__.__class__.__class__.__doc__.__getitem__(_____)).__add__(__name__.__class__.__doc__.__getitem__(___________)).__add__(__name__.__class__.__doc__.__getitem__(___________)))))((______________________:=__name__.__class__.__doc__.__getitem__(_____).__add__(__name__.__class__.__class__.__doc__.__getitem__(__________________)).__add__(__name__.__class__.__doc__.__getitem__(_____)))))
``` python 3.11.0 only
i do not understand
what's going on?
omg it works but how did you get the code for this, is there some brute force method or some application for this
From what I can tell it's joining individual chars to get arbitrary code and running through exec
haha sure sure ```py
from obfuscator import *
o = UnparseObfuscate()
o.object_repr_pair[import] = 'import'
o.visit(parse('import sys'))
'(:=(:=import((:=name.class.doc.getitem((:=name.class().len())).add(name.class.class.doc.getitem((_____:=name.eq(name).pos()))).add(name.class.doc.getitem())))))'
Jsf*ck does a similar thing
you're wrong 🙂
Smh
you got the "joining individual chars" part right though
i should probably write an algorithm to use substrings
actually nvm substrings aren't needed there
what if you take the obfuscated code and run that through the obfuscator again
Then how does it run?
won't work
imports sys
(obfuscated)
i wrote an algorithm from scratch to get numbers
why it works or why it's the way it's idk
what's weird is that sometimes bigger numbers have shorter obfuscations ```py
o.c();o.on(1000) # o.c() resets the obfuscator
'(:=(_____:=(:=(:=(:=name.getitem((__:=name.class().len()))).add().len()).mul().invert().neg()).mul()).mul((:=.lshift((:=(:=name.getitem()).add().add().len())))))'
o.c();o.on(10000)
'(:=(:=(:=(:=(:=name.getitem((:=name.class().len()))).add().len()).mul((:=.mul().invert().neg()))).mul()).mul(___))'
I dead
💀 💀 💀
do number 4
im going to make a list of the numbers 1 to 50 in super obfuscated python
generating a class without using
class:
typeexists :P
how did you make this
i want to try to make import time
they wrote an obfuscator
which obfuscates
too much trolling 😢
print("55191 segmentation fault")
repo?
If you have Git installed, you'll run git clone REPO_URL.git in the command line and it'll download all the files.
Have a look in #❓|how-to-get-help.
Don’t have it installed, do I just pip install git
sudo google how to install git
is this a good python obfuscater?
I would say so
but I'm not the person to ask
it's a conflict of interest for me, since I've contributed to it
would you say its atleast good enough where someone who's never deobfuscated wouldn't be able to easily deobfuscate it by watching a tutorial
again, conflict of interest
but I would say that it's relatively hard to deobfuscate, compared to most obfuscators (most of which just pack the source and then exec it)
to my knowledge there's no tutorials that would cover how to deobfuscate it
Alright appreciate it
Lmao definitely, as herald said there are no resources for how to deobfuscate python. At least not the way that obfuscation works
That's great I've never used anything like this so I don't even know where to start
!e
M=128;W=64
for y in range(H:=32):x=0;exec('z=0;print(end=".#"[len([i for i in range(M+1)if abs(z:=z*z+(x-W/2)*4/W-1+(y-H/2)*4/H*1j)<3])>M]);x+=1;'*W);print()
What the hell
@quartz wave (sorry for ping) i respect you
!e
M=128;W=64
for y in range(H:=32):x=0;exec('z=0;print(end=".#"[len([i for i in range(M+1)if abs(z:=z*z+(x-W/2)*4/W-1+(y-H/2)*4/H*1j)<3])>M]);x+=1;'*W);print()
@dense nova :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | ................................................................
002 | ................................................................
003 | ................................................................
004 | ................................................................
005 | ................................................................
006 | ................................................................
007 | ................................................................
008 | ................................................................
009 | ................................................#...............
010 | ..............................................#.................
011 | .............................................###................
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/zutotehote.txt?noredirect
A little advice guys. How can I remove from a list a complex object?
I've a list with many of these: [{'groupType': 'and', 'filters': [{'dimension': 'country', 'expression': 'AFG', 'operator': 'equals'}]}]
I tried to pass the whole of the above a string representation, but that doesn't work, the same as a compound object.
Since I've a list with many of them, and ideally I'd like to remove all whose dimension is country ... I was trying to find an elegant way that does not require method recursion.
using the del is not an option as it changes the index and it will skip items.
u can loop over copy
or from the end
and del will work
also you can do just a list comprehension like ... for k, v in ... if v[filters][dimension] != country
better go to help channels instead
!e
(lambda: [globals().__setitem__('Test', type("Test", (object,), {"say_hello": (lambda self, i: [globals().__setitem__('''__RV''', None), [[globals().__setitem__('result', "Hello, ")] if i == 1 else [globals().__setitem__('result', "world!")], globals().__setitem__('__RV', result)]].clear() or globals()['__RV'])})), globals().__setitem__('test', Test()), globals().__setitem__('a', test.say_hello(1)), globals().__setitem__('b', test.say_hello(2)), globals().__setitem__('result', a + b), (_:=(__:=__builtins__.__getattribute__((___:=__name__.__class__.__class__.__doc__.__getitem__((______:=(___:=__name__.__getitem__((_____:=__name__.__class__().__len__()))).__add__(___).__len__())).__add__((________:=(________:=__name__.__ne__(__name__).__invert__()).__neg__().__truediv__(________.__add__(________).__neg__()).__rpow__(________).__class__).__doc__.__getitem__((_________:=__name__.__eq__(__name__).__pos__()))).__add__(__name__.__len__().__class__.__doc__.__getitem__(_____)).__add__(__name__.__len__().__class__.__doc__.__getitem__(_________)).__add__(__name__.__class__.__class__.__doc__.__getitem__(_____))))(result)))])()
@dreamy pier :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello, world!
class Test:
def say_hello(self, i):
if i == 1:
result = "Hello, "
else:
result = "world!"
return result
test = Test()
a = test.say_hello(1)
b = test.say_hello(2)
result = a + b
print(result)
!e
(lambda: [(_:=(__:=__import__((___:=__name__.__class__.__doc__.__getitem__((____:=__name__.__class__().__len__())).__add__(__name__.__class__.__class__.__doc__.__getitem__((_____:=__name__.__eq__(__name__).__pos__()))).__add__(__name__.__class__.__doc__.__getitem__(____)))))), (______:=(_______:=__builtins__.__getattribute__((________:=__name__.__class__.__class__.__doc__.__getitem__((__________:=(________:=__name__.__getitem__(____)).__add__(________).__len__())).__add__((____________:=(____________:=__name__.__ne__(__name__).__invert__()).__neg__().__truediv__(____________.__add__(____________).__neg__()).__rpow__(____________).__class__).__doc__.__getitem__(_____)).__add__(__name__.__len__().__class__.__doc__.__getitem__(____)).__add__(__name__.__len__().__class__.__doc__.__getitem__(_____)).__add__(__name__.__class__.__class__.__doc__.__getitem__(____))))((_____________:=_.version))))])()
@dreamy pier :white_check_mark: Your 3.11 eval job has completed with return code 0.
3.11.1 (main, Dec 21 2022, 08:38:55) [GCC 8.3.0]
Thanks @dreamy pier working in the reversed mode did the trick and helped to simplify the code
python/cpython#76357
is this still working or seems to be broken again?
doesn't seem to be possible anymore to hack on a __class__ cell to make super() work in a module level function with no class
For efficiency, in 3.11+ various special cases for functions have been moved into opcodes added to the beginning. That way function calls don't need to check to see if a closure is present etc, it happens automatically. You'll probably need to add them - specifically, COPY_FREE_VARS(n) copies n freevars from the closure to the frame. There's also MAKE_CELL(i) which initialises a cell in that locals slot.
https://docs.python.org/3/library/dis.html#opcode-COPY_FREE_VARS
!e ```py
@type.call
class cout:
def lshift(s,*v):
print(*v,end="",flush=True)
return s
cout << "This is real" << "\n"
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
This is real
now make cin
😔
oh, cool
i tried to make it but the problem was i didn't know getting name is possible, so i could only reach
cin >> "x"
cout << x
i think what he's doing here is checking if the id of the value of the variable is the same as a variable in the globals above the current frame, then assigning the value to that variable
it does have a few issues, if you'd do ```py
a = 0
b = 0
cin >> b
it'd assign it to a
yeah
!e ```py
import dis
dis.dis("a = 0; b = 0; cin >> b")
@earnest wing :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 1 2 LOAD_CONST 0 (0)
004 | 4 STORE_NAME 0 (a)
005 | 6 LOAD_CONST 0 (0)
006 | 8 STORE_NAME 1 (b)
007 | 10 LOAD_NAME 2 (cin)
008 | 12 LOAD_NAME 1 (b)
009 | 14 BINARY_OP 9 (>>)
010 | 18 POP_TOP
011 | 20 LOAD_CONST 1 (None)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ufiqawedih.txt?noredirect
Should be doable with bytecode inspection
!e ```py
import dis
dis.dis("a = 0; b = 0; cin >> b >> a")
@earnest wing :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 1 2 LOAD_CONST 0 (0)
004 | 4 STORE_NAME 0 (a)
005 | 6 LOAD_CONST 0 (0)
006 | 8 STORE_NAME 1 (b)
007 | 10 LOAD_NAME 2 (cin)
008 | 12 LOAD_NAME 1 (b)
009 | 14 BINARY_OP 9 (>>)
010 | 18 LOAD_NAME 0 (a)
011 | 20 BINARY_OP 9 (>>)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ucuyilulod.txt?noredirect
Yeah in the >> you would fetch the previous frame, check the current instruction - 1, and check the co_names at that index
no you cant:```py
dis('cin >> a[b]')
0 0 RESUME 0
1 2 LOAD_NAME 0 (cin)
4 LOAD_NAME 1 (a)
6 LOAD_NAME 2 (b)
8 BINARY_SUBSCR
18 BINARY_OP 9 (>>)
22 RETURN_VALUE
in this case `cin` should assign to `a[b]` like this: `a[b] = something`
last instructions are: ```py
6 LOAD_NAME 2 (b)
8 BINARY_SUBSCR
``` so you cant know where you should assign to from looking at them
who said we can't
with a little bytecode tinkering we can
I was replying to this:
Yeah in the >> you would fetch the previous frame, check the current instruction - 1, and check the co_names at that index
With a lot of bytecode pain you of course can do it
ok
an error in it is "check the co_names at that index"
the instruction can also be checking co_varnames, co_cellvars, or co_freevars
funny
cin >> a
cin >> a.b
cin >> a[b]
cin >> (a, b)
cin >> (a, *b)
# cin >> [a, b][c] # assign only to a or b // no that doesnt make any sense
# some complex example:
cin >> a.b()[c, d]
# some invalid examples:
cin >> 1
cin >> []
cin >> a()
it also cant work without defining variable before cin >>. To do that you should:
- patch bytecode (like
@supports_cindecorator) - set bytecode trace function
- ?
some time ago i was implementing cfor iterator. It looked like this: py for x in cfor( 'i, j = 3, 4', 'i * j < 1000', 'i += 1; j += 2', 'i ^ j', ): print(i, j, x) it is equivalent to this in C: ```c
for (int i = 3, j = 4; i * j < 1000; i += 1, j += 1) {
int x = i ^ j;
// body
}
lmao
it's like jack's format thingy
its broken, it works only with global variables, i dont know how to fix it: ```py
from future import annotations
from types import CodeType
from typing import Any, Iterator
import sys
class cfor:
_init: CodeType
_cond: CodeType
_inc: CodeType
_val: CodeType
def __init__(
self,
init: str = '',
cond: str = 'True',
inc: str = '',
val: str = 'None',
) -> None:
self._init = compile(init, '<cfor initialisation>', 'exec')
self._cond = compile(cond, '<cfor condition>', 'eval')
self._inc = compile(inc, '<cfor increment>', 'exec')
self._val = compile(val, '<cfor value>', 'eval')
self.ns = sys._getframe(1).f_globals
def __iter__(self) -> Iterator[Any]:
ns = self.ns
cond = self._cond
val = self._val
inc = self._inc
exec(self._init, ns, ns)
while eval(cond, ns, ns):
yield eval(val, ns, ns)
exec(inc, ns, ns)
i: int
j: int
def main() -> None:
for x in cfor(
'i, j = 3, 4',
'i * j < 1000',
'i += 1; j += 2',
'i ^ j',
):
print(i, j, x)
if name == 'main':
main()
PyPy is a python interpreter written in python.
So it can run python code. But what interpreter is running PyPy? Can PyPy run itself?
"what interpreter" probably depends on what there is installed
oh, there is a big file libpypy3-c.dll, probably it is a CPython interpreter and all PyPy's code
In the Python snippet you increment j by 2 but in the C snippet you increment it by 1
to bypass needing to explicitly define a default value, you can go the C way and give a type declaration using a patched __annotations__
so ```py
annotations = ...
a: int
cin >> a # all is good in the world
alternatively, you can do the whole thing in a class scope letting you control all variable access lmao
class Main(C):
a: int; # or int: a; for fun
b: float;
cin >> a >> b;
cout << "Your values are " << a << " and " << b << "!";
from sys import _getframe
from ctypes import pythonapi, c_void_p, c_int
PF_LTF = pythonapi.PyFrame_LocalsToFast
PF_LTF.argtypes = [c_void_p, c_int]
@lambda c:c()
class __annotations__(dict):
def __setitem__(self, name, typ, *, builtin_can_init={int, str, tuple}):
frame = _getframe(1)
if name in frame.f_locals:
if isinstance(type(frame.f_locals[name]), typ):
return super().__setitem__(typ, name)
if typ in builtin_can_init:
frame.f_locals[name] = typ()
else:
frame.f_locals[name] = None
if frame.f_locals is not frame.f_globals:
PF_LTF(frame)
return super().__setitem__(typ, name)
``` this can work
I do like the decorator
what does that decorator even do
updated with constants ```py
from sys import _getframe
from ctypes import pythonapi, c_void_p, c_int
PF_LTF = pythonapi.PyFrame_LocalsToFast
PF_LTF.argtypes = [c_void_p, c_int]
@lambda c:c()
class annotations(dict):
def setitem(self, name, typ, *, builtin_can_init=[(int, 0), (str, ""), (tuple, ())}):
frame = _getframe(1)
if name in frame.f_locals:
if isinstance(type(frame.f_locals[name]), typ):
return super().setitem(typ, name)
for btyp, default in builtin_can_init:
if isinstance(typ, btyp):
frame.f_locals[name] = default
break
else:
frame.f_locals[name] = None
if frame.f_locals is not frame.f_globals:
PF_LTF(frame)
return super().setitem(typ, name)
@lambda c:c()
class A:...
``` is the equivalent of ```py
class A:...
A=A()
so it just effectively transforms the class A into an instance of itself
yes
-> A is no longer the class A, but an instance of class A
interesting
i wonder how that looks in bytecode
it should be exactly equal to ```py
class A:...
A=(lambda c:c())(A)
it is
yeah its just Abc = (lambda _:_())(__build_class__(class_builder, "Abc"))
aka Abc = (lambda _:_())(Abc)
seems like lower decorators go first
Yeah, thats typo
That wouldn't work inside functions, because their annotations has no effect in runtime
Not exactly. In your case "A" var is assigned twice, but actually it happens only once.
Also, decorator it evaluated before class/function.
eh yeah maybe
That's true. In any way you need some way of controlling the context, so maybe the class approach is the "best"?
your variable assignments are the wrong way around-
should go type: name = value; instead of name: type = value;
actually, would you mind if i used that for a project of mine
thats a fun idea
we just need to combine it with this now
Yes, do whatever you want.
nice ```pycon
int: test = 4
int test
test = 5.3
test
5
it does it's best to convert it from whatever the value is to the correct type
so if you set it's type to str, you can set the value to just about anything
and it'll just happily work
it ends up calling type_of_var(value)
so in this case, it's int(5.3)
i think i broke it ```pycon
test = type('',(),{'new':lambda _,x:x})
test: a = 5
test a
a
Traceback (most recent call last):
File "<stdin>", line 6, in getitem
KeyError: 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 9, in getitem
KeyError: 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 12, in getitem
AttributeError: module 'builtins' has no attribute 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 14, in getitem
NameError: a is not defined
it never assigned a value to test because it wasn't type annotated
do type: test = ...
and it should work
well, i gtg
lmk if you find a bug or there's anything you want me to add
have a nice day everyone
That moment when it should return NameError but it returns three other errors too
that's because they're not using the modular version
i had to make it do that to make it short enough to send in discord, but in the actual module, it just prints the NameError
instead of printing all that
did not fix it ```pycon
type: test = type('',(),{'new':lambda _,x:x})
type test
test: a = 5
test a
a
Traceback (most recent call last):
File "<stdin>", line 6, in getitem
KeyError: 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 9, in getitem
KeyError: 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 12, in getitem
AttributeError: module 'builtins' has no attribute 'a'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 14, in getitem
NameError: a is not defined
copied
ah
that one is outdated
ok
here's the source for the module
https://github.com/Resuscitating/c-in-py/blob/main/c.py
if you want to use that instead
put these at the top of your main file, or before you run anything else in a REPL
from __future__ import annotations
import c
and then it should be enabled
done
and um ```pycon
type: test = type('',(),{'new':lambda _,x:x})
test: a = 5
a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\user\c.py", line 29, in getitem
raise NameError(f"{item} is not defined")
NameError: a is not defined
test somehow converted to int ```pycon
test
<class 'int'>
thats very much not meant to happen
ok im gonna go try to fix this brb
im pretty sure i found the problem
it might work now
but dont trust that
nope
still breaks
ah i know why it breaks
fixed it
i think
probably works now
yep
it works
at least, with my limited testing
>>> from __future__ import annotations; import c
>>> type: test = type("", (), {"__init__":(lambda s, A:None)})
>>> test: b = 1
>>> test
<class '__main__.'>
>>> b
<__main__. object at 0x7f6e0c327040>
@quartz wave sorry for the ping but you seemed like you wanted to use the module and now it works so I thought I'd let you know
Morning folks,
I'm getting confused on the role of the __all__ . Somehow I thought this would have also avoided the IDE not to see a particular class from the autocomposing, but this doesn't seem to be the case?
Can somebody advice? I'm sure I'm doing something wrong.
Pretend a directory structure like this:
= dir_with_my_packace
|__ module1.py
|___ Class A
|___ Class B
|__ module2.py
|___ Class C
In my dir_with_my_package I put the file __init__.py with the following content:
from dir_with_my_packace.module1 import ClassA
from dir_with_my_packace.module2 import ClassC
__all__ = ['ClassA', 'ClassC']
But in the IDE, when I do type dir_with_my_packace. ClassB is shown too.
What am I doing incorrecty?
Wrong channel for this, maybe ask in #editors-ides (and include the name of your IDE)
Thanks
keyword args can be considered esoteric themselves jesus fucking christ
"Store the last n consts on the stack into keywords from const pool i, n being len(consts[i])" statements dreamed up by the utterly deranged
Esoteric phyton
Hi do you know a mathematical function that takes a number and doing some funky and complex stuff but in the end returns the same value?
Almost non readable function
depends on what inputs you want to accept
if it's just integers i'd probably abuse taylor series and the like by truncating them and then rounding when the terms become negligibly small
Oh I know a nice place to start
It only works for positive integers though
If f(n) is amount of coprimes with n less than n, then sum of f(n) for each n that divide k is k
i made one that takes a number and converts it into a crazy expression
Ok guys i really appreciate
Can i see soruce code?
A lambda that replaces functools.reduce. ```py
red = lambda f, a: f(((a := (*a,)), [f(t, a[i+1]) for i, t in enumerate(a[-1:])])[1][-1], a[0])
print(red(lambda a, b: a + b, [1, 2, 3]))
i raise you recursion
red=lambda f,a,r=None:red(f,a[1:],a[0]if r is None else f(r,a[0]))if a else r
comes with an initial value as well
call stack begging for mercy
Here, (a := (*a,)) ensures that it can work on any iterator, not just on lists and tuples.
>>> sum(int(x)for x in str(x))
6
>>> sum(int(x)for x in f'{x}')
6
>>> sum(map(int,str(x)))
6
>>> sum(map(int,f'{x}'))
6
ty
is there a good way to import the same file multiple times?
preferably in a way such that each instance won't overrides the other one's variables
if it's removed from sys. modules, it should create a new instance
wdym
one sec im testing
!e
import sys
l = []
import time
l.append(time)
del sys.modules["time"]
import time
print(l[0] is time)
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
False
two different instances of time
might not work with some modules
bc some are needed
but that should work in general
for my use case it works as I just want the user to not know Im running their code in threads
thanks a lot 🙂
np
How could i make a 1-liner out of this? I guess i'm missing something but i kinda dont understand what 🤷
'''
Convert rgb to hex
def rgb(r, g, b):
buffer = ''
for i in [min(r, 255), min(g, 255), min(b, 255)]:
if i not in range(0, 256):
buffer+='00'
else:
if len(str(hex(i)[2:])) == 1:
buffer+=f'0{str(hex(i)[2:])}'
else:
buffer+=str(hex(i)[2:])
return buffer.upper()
'''
def rgb(r, g, b):
return ''.join(['00' for i in [min(r, 255), min(g, 255), min(b, 255)] if i not in range(0, 256) else (f'0{str(hex(i)[2:])}' if len(str(hex(i)[2:])) == 1 else str(hex(i)[2:]))]).upper()
rgb=lambda r,g,b:"".join(f"{min(255,max(0,a)):2X}"for a in(r,g,b))
might need [2:] haven't tested
i mean this does work however it doesn't work correctly in cases like (0, 0, 0)
you could use bytes.hex
rgb = lambda r, g, b: '#' + bytes(min(255, max(0, n)) for n in (r, g, b)).hex()```
woah, this is exactly what i needed, thanks, ill look into how it works 👍
I'm like 90% sure this does the same thing
rgb=lambda*c:'#'+b"".join(map(lambda n:bytes(min(255,max(0,n))),c)).hex()```
haven't tested it though
so idk
actually, generator is shorter than map here
rgb=lambda*c:'#'+bytes(min(255,max(0,n))for n in c).hex()```
!e
class _int_t:
def __init__(self, ln, s):
self.ln = ln // 8
self.s = s
def __gt__(self, other):
return int.from_bytes(other[0:self.ln], 'little', signed=self.s)
@type.__call__
class reinterpret_cast:
def __lt__(self, other):
return True
uint32_t = _int_t(32, False)
int32_t = _int_t(32, True)
uint16_t = _int_t(16, False)
int16_t = _int_t(16, True)
uint8_t = _int_t(8, True)
int8_t = _int_t(8, True)
if __name__ == '__main__':
print(reinterpret_cast<uint32_t>(b'pytn'))
print(reinterpret_cast<int32_t>(b'cast'))
print(reinterpret_cast<uint16_t>(b'to'))
print(reinterpret_cast<int16_t>(b'in'))
print(reinterpret_cast<uint8_t>(b't'))
print(reinterpret_cast<int8_t>(b's'))
@pearl socket :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 1853127024
002 | 1953718627
003 | 28532
004 | 28265
005 | 116
006 | 115
you can do
@type.__call__
class reinterpret_cast:
...
instead of reinterpret_cast = _reinterpret_cast()
ah nice
absolutely cursed
!e This can be cleaned up pretty easily, and it cheats a bit but it works```py
class Number:
def init(self, value):
self._in_middle = False
self._value = value
def __lt__(self, other):
return other._value if isinstance(other, Number) else other
def __eq__(self, other):
return self._value == other._value if isinstance(other, Number) else self._value == other
def __pos__(self):
if self._in_middle is False:
self._value += 1
self._in_middle = not self._in_middle
return self
def __neg__(self):
if self._in_middle is False:
self._value -= 1
self._in_middle = not self._in_middle
return self
def __str__(self):
return str(self._value)
class NonPythonLoop:
def init(self, start, end, _):
self._curr = start
--self._curr
--self._curr
self._end = end
def __bool__(self):
++self._curr
return not self._curr == self._end
incr = Number(5)
print(incr)
++incr
++incr
print(incr)
--incr
print(incr)
print()
loop = NonPythonLoop(i := Number(0), i < 5, ++i)
while loop:
print(i)
@meager zinc :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 5
002 | 7
003 | 6
004 |
005 | 0
006 | 1
007 | 2
008 | 3
009 | 4
nice, though the loop only increments
why not have Number.__pos__ and Number.__neg__ set an attribute on itself
and then the loop can check that attribute on _ to see what to do
possibly
but that would only work for ++ and --
also ++++incr is possible
which looks absolutely stupid
you could also do
print(+-incr)
print(-incr)
print(+-+incr)
also don't you mean to flip in_middle before modifying the value? because rn +incr should increment it I think
<@&831776746206265384> ads
!tempban 1062653593162891335 14d It seems like you're only here to post an ad. Please reread our rules before coming back.
:incoming_envelope: :ok_hand: applied ban to @ornate fractal until <t:1674644977:f> (14 days).
!e py __import__('pickle').loads(bytearray(map((lambda x:x-4),__import__('gzip').decompress(bytearray(map((lambda x:x-1 if x!=0xff else x),[1,1,1,92,39,114,106,209,1,145,131,49,206,133,104,59,52,171,26,6,102,198,214,43,198,6,6,154,63,3,10,139,161,11,163,221,179,147,139,161,115,163,221,139,131,221,203,181,159,3,153,94,77,200,12,70,188,135,126,50,160,41,206,79,41,45,225,77,104,51,12,244,212,115,76,148,185,20,2,3,195,26,153,226,108,255,3,100,191,154,235,1,9,140,32][::-1]))))))
@split salmon :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello world!
Fabulous
ensnared@snare:~$ cat test.c
#include <stdio.h>
int main() {
int x = 41;
printf("%d\n", +x);
return 0;
}
ensnared@snare:~$ gcc test.c
ensnared@snare:~$ ./a.out
41
+lvalue doesn't increment
I admit I'm not clear what you're doing but it feels like you meant to do this:
return (other._value if isinstance(other, Number) else other) > self._value
def __eq__(self, other):
return (other._value if isinstance(other, Number) else other) == self._value```
i'm talking about the python class
it increments and then skips the next increment
skipping the increment and then incrementing is probably better
i think it just needs to start with self._in_middle as True
instead of starting as False
yeah that'd work too
i misunderstood what you were saying originally though- thanks for clarifying
iirc someone implemented incrementing and decrementing with frame hackery and bytecode parsing
here, cereal did decrementing
Yo
What would be the shortest way to check if all words in the list have the same length
this should do that all(map(len(l[0]).__eq__,map(len,l)))
as long as there's elements in the list and they're all iterables
Ah sorry
all good
Well, just for comparison I'll send my solution
ooh ok
len(k[0])*4==len(''.join(k[1,5]))
k is a list of words
There is 5 words in the list
It doesn't matter in my case
i think yours fails with ["a", "", "bc", "d", "e"]
Lets say that list will always have 5 elements
yep
it returns true
Ooh you are right
this is shorter
all(len(e)==len(l[0])for e in l)
len({*map(len,l)})==1

<= if empty list counts
len({*map(len,l)})<2
only works if the stuff in the iterable is hashable tho
question was about "words" so i guess yes
No, it works for any Iterable[Sized] object
the iterable returns ints because len
oops already mentioned
ooh that's good
ooh
introducing things that were never meant to be: pseudo labels in python
oh hey
labels
I once implemented those
the only think I had was unconditional jumps though
never got around to adding conditionals :(
my eyes
ctypes code be like
i do, thank you
what's the point of this?
Memory bugs in python, mostly for fun
or rather, what can it achieve?
that specific file allows for loading an arbitrary address as an object (via a bug in the LOAD_CONST opcode)
do i hear arbitrary code execution 🙂
eh
maybe actually
mhm
the python runtime still does python things, so you'd need to hide a python function or code object in memory, then load and execute it
i doubt you could get it to run shellcode
you're correct
but the ability to load arbitrary memory addresses as objects could still be damaging
it would be quite funny
it would
but i still have no idea how it works
well its quite simple, when a bug in the LOAD_CONST opcode allows an arbitrary address to be loaded as an object, it means that the virtual machine is not properly checking the address before loading it from memory, from there i assume you know the issues with that and how it could lead to exploitation
well yeah i know what it does
but i dont know how to get the overflow
oh i misunderstood
i do know that its something with EXTEND_ARG, and i have an assumption, but i have no idea otherwise
my assumption is that LC just goes into the const pool at index i and doesnt check if that index is actually still in the pool
If the index passed to the opcode is not within the range of the constant pool or if the constant pool entry at that index is not the expected type it could cause the program to access memory outside of the intended buffer, resulting in a buffer overflow vuln. It's something you should look into if youre interested
i certainly find python bugs interesting
ik what a buffer overflow is, i just dont know enough about the cpy internals to know if that's actually what is happening
but if it is, that would be quite the funny
wouldn't be of that much use other than maybe obfuscation tho
yeah true
it is indeed overflow/underflow
!e ```py
f=lambda s,k:"".join(chr([ord(c),(ord(c)+k-97)%26+97,(ord(c)+k-65)%26+65][c.isalpha()+c.isupper()])for c in s)
@sick hound :warning: Your 3.11 eval job has completed with return code 0.
[No output]
!e
(lambda _, __, ___, ____, _____, ______, _______, ________:
getattr(
__import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
().__class__.__eq__.__class__.__name__[:__] +
().__iter__().__class__.__name__[_:][_____:________]
)(
_, (lambda _, __, ___: _(_, __, ___))(
lambda _, __, ___:
bytes([___ % __]) + _(_, __, ___ // __) if ___ else
(lambda: _).__code__.co_lnotab,
_ << ________,
(((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __)
- _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ <<
__) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______
<< ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) <<
((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) <<
__) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______
<< (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) +
_) << ((((___ << __) + _) << _))) + (((_______ << __) - _) <<
(((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ <<
_))) + (_____ << ______) + (_ << ___)
)
)
)(
*(lambda _, __, ___: _(_, __, ___))(
(lambda _, __, ___:
[__(___[(lambda: _).__code__.co_nlocals])] +
_(_, __, ___[(lambda _: _).__code__.co_nlocals:]) if ___ else []
),
lambda _: _.__code__.co_argcount,
(
lambda _: _,
lambda _, __: _,
lambda _, __, ___: _,
lambda _, __, ___, ____: _,
lambda _, __, ___, ____, _____: _,
lambda _, __, ___, ____, _____, ______: _,
lambda _, __, ___, ____, _____, ______, _______: _,
lambda _, __, ___, ____, _____, ______, _______, ________: _
)
)
)
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello world!
Yay
cool
what in the ever loving fuck
It’s esoteric python
!e
f=lambda s,k:"".join(chr([ord(c),(ord(c)+k-97)%26+97,(ord(c)+k-65)%26+65][c.isalpha()+c.isupper()])for c in s)
print(f('abs', 2))
ord(c)+k
@dense nova :white_check_mark: Your 3.11 eval job has completed with return code 0.
cdu
Ah
Good now explain how this works
using co_nlocals to index into a tuple of lambdas, then using co_argcount to get numbers from those
doing bitshifts with those numbers
doing some indexing into builtin type names to build a string
and so on
Never heard of co_nlocals
If you scroll thru this channel I have posted a number of POCs for bugs to produce arbitrary write primitives, but since they all require code execution already they aren't too bad
It's not a Python bug that mal-formed bytecode can crash things.
agree, seems rather misleading to say that the bug is within python, unless you can provide python code that compiles to that malformed bytecode
(or maybe i misunderstand)
euler = lambda steps: __builtins__.sum([1/(__import__('math').factorial(i)) for i in __builtins__.range(steps)])
how can i make this more esoteric? is there something for keywords like with builtin functions?
map
instead of for loop
iter instead of range
def a():
try:
a()
except:
a()
a()
It caused python core dump, but it seems like with newer versions it doesn't work.
Now prints a whole lot of traceback.
!e ```py
import sys
sys.setrecursionlimit(8) # speed up a little
def a():
try:
a()
except:
a()
a()
@austere mauve :x: Your 3.10 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 5, in a
003 | RecursionError: maximum recursion depth exceeded
004 |
005 | During handling of the above exception, another exception occurred:
006 |
007 | Traceback (most recent call last):
008 | File "<string>", line 5, in a
009 | File "<string>", line 7, in a
010 | RecursionError: maximum recursion depth exceeded
011 |
... (truncated - too many lines)
Full output: too long to upload
In 3.9 it crashes python, 3.10 creates a large traceback and I'm not sure what happens with 3.11
what
Look at this
This is a hello world print
@winged turtle
It's the same thing as what you were trying to do
You were going to do multiple actions that could be done with just 1
!e and the code
!e print("test")
@winged turtle :white_check_mark: Your 3.11 eval job has completed with return code 0.
test
okay thanks
!e input("enter weight:")
Weight = int(input())
input("enter height:")
Height = int(input())
wh2 = WeightHeight**2
bmi = wh2703
print(bmi)
@winged turtle :x: Your 3.11 eval job has completed with return code 1.
001 | enter weight:Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | EOFError: EOF when reading a line
input() probally doesn't work with the bot 🤷♂️ for obvious reasons.
!e ```input("enter weight:")
Weight = int(input())
input("enter height:")
Height = int(input())
wh2 = WeightHeight**2
bmi = wh2703
print(bmi)
@winged turtle :x: Your 3.11 eval job has completed with return code 1.
001 | enter weight:Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | EOFError: EOF when reading a line
Your code is wrong tho
i did what I was told
You're trying to do
input(text)
Var = input()
When you want to either do
Var = input(text)
Or
print(text, end="")
var = input()
!e Weight = int(input('enter weight:'))
Height = int(input('enter height:'))
wh2 = WeightHeight**2
bmi = wh2703
print(bmi)
@winged turtle :x: Your 3.11 eval job has completed with return code 1.
001 | enter weight:Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | EOFError: EOF when reading a line
Here's how to format Python code on Discord:
```py
print('Hello world!')
```
These are backticks, not quotes. Check this out if you can't find the backtick key.
!e ```Weight = int(input('enter weight:'))
Height = int(input('enter height:'))
wh2 = WeightHeight**2
bmi = wh2703
print(bmi)
@winged turtle :x: Your 3.11 eval job has completed with return code 1.
001 | enter weight:Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | EOFError: EOF when reading a line
there
Yep
wair one sec
!e ```py
Weight = int(input('enter weight:'))
Height = int(input('enter height:'))
wh2 = WeightHeight**2
bmi = wh2703
print(bmi)
@winged turtle :x: Your 3.11 eval job has completed with return code 1.
001 | enter weight:Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | EOFError: EOF when reading a line
I swear I saw color before
It won't work with the bot anyways because of the inputs
am I stupid or is there actually a way to get colored text?
You specify the language after first tree backticks
i did
Not everything gets colored tho
Yep, it's just the fact that some stuff gets colored and some doesnt
what gets colored
Keywords, some functions, etc etc. I don't really exactly know it
my dumb ass multiplied instead of divided
Does it even work on mobile
!e
print(__builtins__.sum([1, 2, 3]))
@karmic pumice :white_check_mark: Your 3.11 eval job has completed with return code 0.
6
what
Is this how BMI is calculated?
ooo I just thought of something dun
nonono i messed up
lemme show u the right script
i dont think this app works
it gave me 0
It's just weight / (height**2)
What’s **
Exponentiation
^ in python is bwise xor iirc
!e
print((2^2), (0^1))
@karmic pumice :white_check_mark: Your 3.11 eval job has completed with return code 0.
0 1
Why do you multiply by 703
I think he doesn't understand that height needs to be in meters
who
You
wdym
The height you input should be in meters
that would give me an absurd number
And then you need to use float instead of int
Because you don't need to multiply by 703
Writing from phone is such a pain lmao
703 is probably conversion from metric/imperial
but no one puts it in meters
i was gonna make the script let u enter feet and inches
not that complicated but yeah
that's probably where it came from
"yeah im 1.626 meters tall) 💀
Wtf does 703 come from lmao
i have no idea
What if someone is 6'10?
if inches are based on the metric system why are we having problems with converting
(also not the appropriate channel)
anyway
1m = ~40 inches
1kg = ~2.2 pounds
40²/2.2 = ~750
we'll make it appropriate maybe
Well if they enter 610 then it will break
Not really break but won't act as we need it to
6'10"
that's how to write it
!e 18.707763671875/1.703125
@winged turtle :warning: Your 3.11 eval job has completed with return code 0.
[No output]
okay ill just use a calculator then
69 ```py
w,h=eval("int(input('enter %seight:')),"2%('wh',));print(w*703/h/h)
uhm
K lmao this is esoteric enough ahaha
lmao that format map
divide height twice
You need your code to work with any numbers
also please move to an appropriate channel if possible
!e
sussy = 34
baka = 35
print (sussy + baka)
@winged turtle :white_check_mark: Your 3.11 eval job has completed with return code 0.
69
one sec
oh wtf
why does that not work
oh nvm
im stupid
wait a minute...
oh nvm yeah it works
72 but more esoteric ```py
print(eval(("int(input('enter %seight:'))*703/"2)[:-5]%('wh',)+'**2'))
you could do a double eval instead of int 
inb4 rm rf height
ima stick with beginner stuff for now
@karmic pumice i think print is better after all. When you use input, it limits the amount of characters you can type
you're in the wrong channel-
use #bot-commands for various bot functions
#esoteric-python is for esoteric python
!e Credit to @gritty mesa and @subtle solar for the original concept in the TIL post (#1055288361629274112 message)
Turns out you can integrate an entirely different language in python. As a demonstration, here is brainf:
from __future__ import annotations
@lambda _:_()
class __annotations__:
def __setitem__(self, v, p):
if v.endswith("_BF"):
s=[i:=0];c=''
for o in p:c+=' '*i+[f'i+=1\n{" "*i}if i>=len(s):s+=[0]','i-=1','s[i]+=1','s[i]-=1','print(end=chr(s[i]))','s[i]=ord(__import__("sys").stdin.read(1))','while s[i]:','s','']['><+-.,['.find(o)]+'\n';i+=(92-ord(o))*(o in'][')
exec(c);globals()[v]=s
var_BF: "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
print(var_BF)
@meager zinc :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | Hello World!
002 | [0, 0, 72, 100, 87, 33, 10]
they told me to go here ;-;
also im switching to insitux
who did?
well they brought me here
one sec
ill find it
NikIta#3695 told me to go there and then started teaching me stuff about python
here*
this channel is for esoteric python
we're happy to teach esoteric python, but this channel isn't for normal python or bot spam
^
for future reference #❓|how-to-get-help would be better if you want to get help outside from #python-discussion
pyto. Just needed a quick one to test my script on my phone
Its not available on playstore ...
im on an iphone
>>> print(object.__repr__(1))
<int object at 0x00007FFEC786D328>
now introducing: yes ```py
print(True | True << True | True << (True | True << True) | True << (True << (True << True)) | True << (True | True << (True << True)) | True << (True << True | True << (True << True)))
!e print(True | True << True | True << (True | True << True) | True << (True << (True << True)) | True << (True | True << (True << True)) | True << (True << True | True << (True << True)))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
123
Why
and optimized it
It’s just bitwise operators isn’t it?
it is
its basically just reconstructing the int one bit at a time
BT_TRUE = lambda: Constant(True)
def transform_bits(node: Constant):
ic: int = node.value
if ic == 0:
return node
bits = []
while ic > 0:
msk = ic & 0b1
bits.append(msk)
ic >>= 1
conv_bits = zip(bits, range(len(bits)))
conv_bits = list(filter(lambda x: x[0] == 1, list(conv_bits)))
if len(conv_bits) == 0:
conv_bits = [(0, 0)]
sm = BinOp(
left=BT_TRUE(), # this will always be true
op=LShift(),
right=Constant(conv_bits[0][1])
) if conv_bits[0][1] != 0 else BT_TRUE()
for x in conv_bits[1:]:
sm = BinOp(
left=sm,
op=BitOr(),
right=BinOp(
left=BT_TRUE(), # this will always be true
op=LShift(),
right=Constant(x[1])
)
)
return sm
here is the ast
What’s ‘ast’?
abstract syntax tree
representing python source as a list of nodes
I see
Is this a good way to obfuscate? Id probably say not?
certainly makes it harder to understand
but all you need to deobfuscate that is to put it into the python repl
Yeah, to the average readers they’ll have no clue what’s going on though
here's how ast looks btw
you can manipulate that really easily and tell ast to turn it back into py source
which makes this entire thing a trillion times easier
Im not entirely sure what ast is still 😟
its just python code represented as a tree
which you can modify
and turn back into source
modifying source code is really easy with this
Interesting
Do you think you could run eval with using that type of obfuscation
wdym
!e
print(True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True))))))))))))))))
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | File "<string>", line 1
002 | print(True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True))))))))))))))))
003 | ^
004 | SyntaxError: '(' was never closed
one more
!e
print(True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True | (True << (True)))))))))))))))))
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | OverflowError: too many digits in integer
Yeah I am not good with this 😂
just a quick heads up, this is equivalent to 1 | (1 << (1 | (1 << (1 | (1 << (1 | (1 << 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168193))))))))))
you were bitshifting left by 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168193
aka a binary number with 1 one and 26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168193 zeroes
Whoops
#bot-commands
i love the idea of manipulating an ast
I’m scared
like it kinda cuts out all the fluff of having to code in a text file, all these silly issues with whitespace go away
thats exactly what its for
yes
modify to your hearts content without having to worry about the actual source code
i want to get good at it
its very easy to get good at it
are you good, if so where did you start?
remember these 3 things:
- smoke crack while using it
- contemplate your life while using it
fix_missing_locations
lol
i started with the crack step
Print the number 14 with it
Call(
func=Name("print", Load()),
args=[Constant(14)],
keywords=[])
No no, with the bitwise operators
what does load do?
Call(
func=Name(id='print', ctx=Load()),
args=[
BinOp(
left=BinOp(
left=BinOp(
left=Constant(value=True),
op=LShift(),
right=Constant(value=True)),
op=BitOr(),
right=BinOp(
left=Constant(value=True),
op=LShift(),
right=BinOp(
left=Constant(value=True),
op=LShift(),
right=Constant(value=True)))),
op=BitOr(),
right=BinOp(
left=Constant(value=True),
op=LShift(),
right=BinOp(
left=Constant(value=True),
op=BitOr(),
right=BinOp(
left=Constant(value=True),
op=LShift(),
right=Constant(value=True)))))],
keywords=[])
provides context for what you're doing with the name
Load() means "load this name"
This doesnt look cool like the True one
it is the True one
so i wanna take this symbol that the interpreter should know about and i want to load it
is it loaded into the global dict
print(True << True | True << (True << True) | True << (True | True << True)) this is the actual thing
is that the load destination?
wdym
ah ok
Name("abc", Load()) is basically abc
ah ok
Name("abc", Store()) will never occur on its own, but basically means abc = something
Not too bad
this is how a Store() would look
the args don't exist in this case
args are only for the Call node
aka a function call
i have an gui instance creator i will show you
it would be fun with ast
works with databases
damn
getattr(__import__("random"), "choice")([“sleep”, “don’t sleep”])
This article is pretty cool: https://benkurtovic.com/2014/06/01/obfuscating-hello-world.html
Fun with functional programming in Python | Ben Kurtovic's blog
how can I get the letters r and h using something like
str.__class__.__name__[3]
@sharp moon :white_check_mark: Your 3.11 eval job has completed with return code 0.
r
!e ```py
print(int.doc.doc.class.class.getattribute.str.str.str()[4])
@earnest wing :white_check_mark: Your 3.11 eval job has completed with return code 0.
h
etc.
!e
getattr(import(().class.eq.class.name[1] +().class.eq.class.name[2] + round.class.name[6] + dir.name[0] + round.class.name[14] + map.name[0]), round.class.name[11] + hex.name[0] + round.class.name[14] + True.class.name[1] + round.class.name[11] + str.class.name[3])([1, 2])
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | AttributeError: module 'random' has no attribute 'chooce'. Did you mean: 'choice'?
!e getattr(import(().class.eq.class.name[1] +().class.eq.class.name[2] + round.class.name[6] + dir.name[0] + round.class.name[14] + map.name[0]), round.class.name[11] + hex.name[0] + round.class.name[14] + id.name[0] + round.class.name[11] + str.class.name[3])([1, 2])
@sick hound :warning: Your 3.11 eval job has completed with return code 0.
[No output]
Hmm why’s it not choosing a number
You need to print it
!e py print(getattr(__import__(().__class__.__eq__.__class__.__name__[1] +().__class__.__eq__.__class__.__name__[2] + round.__class__.__name__[6] + dir.__name__[0] + round.__class__.__name__[14] + map.__name__[0]), round.__class__.__name__[11] + hex.__name__[0] + round.__class__.__name__[14] + id.__name__[0] + round.__class__.__name__[11] + str.__class__.__name__[3])([1, 2]))
@last locust :white_check_mark: Your 3.11 eval job has completed with return code 0.
1
!e print(getattr(import(().class.eq.class.name[1] + ().class.eq.class.name[2] + round.class.name[6] + dir.name[0] + round.class.name[14] + map.name[0]), round.class.name[11] + hex.name[0] + round.class.name[14] + id.name[0] + round.class.name[11] + str.class.name[3])([1, 2]))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
1
On mobile text doesn’t get coloured
It does on android 
!e print(getattr(import(().class.eq.class.name[1] + ().class.eq.class.name[2] + round.class.name[6] + dir.name[0] + round.class.name[14] + map.name[0]), round.class.name[11] + hex.name[0] + round.class.name[14] + id.name[0] + round.class.name[11] + str.class.name[3])([100, 2]))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
100
!e print(getattr(import(().class.eq.class.name[1] + ().class.eq.class.name[2] + round.class.name[6] + dir.name[0] + round.class.name[14] + map.name[0]), round.class.name[11] + hex.name[0] + round.class.name[14] + id.name[0] + round.class.name[11] + str.class.name[3])([26485842168683588, 2]))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
2
!e print(getattr(import(().class.eq.class.name[1] + ().class.eq.class.name[2] + round.class.name[6] + dir.name[0] + round.class.name[14] + map.name[0]), round.class.name[11] + hex.name[0] + round.class.name[14] + id.name[0] + round.class.name[11] + str.class.name[3])([100, 2]))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
2
!e print(getattr(import(().class.eq.class.name[1] + ().class.eq.class.name[2] + round.class.name[6] + dir.name[0] + round.class.name[14] + map.name[0]), round.class.name[11] + hex.name[0] + round.class.name[14] + id.name[0] + round.class.name[11] + str.class.name[3])([100, 2]))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
2
But it printed 100 just now
it's print(__import__('random').choice([100, 2]))
Oh
I think I should actually learn what it is before trying
Never knew you could can just import and print in one line
!e print(__import__('time'))e)
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | File "<string>", line 1
002 | print(__import__('time'))e)
003 | ^
004 | SyntaxError: unmatched ')'
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | File "<string>", line 1
002 | print(__import__('time')e)
003 | ^^^^^^^^^^^^^^^^^^^
004 | SyntaxError: invalid syntax. Perhaps you forgot a comma?
!e ```py
print(import('time'))
@austere mauve :white_check_mark: Your 3.11 eval job has completed with return code 0.
<module 'time' (built-in)>
I want it to import time AND print “e”
!e
print(__import__("time"), "e")
@austere mauve :white_check_mark: Your 3.11 eval job has completed with return code 0.
<module 'time' (built-in)> e
Or
!e
print(__import__('time') and 'e')
@low lynx :white_check_mark: Your 3.11 eval job has completed with return code 0.
e
!e ```py
(import("time"),print("e"))
@austere mauve :white_check_mark: Your 3.11 eval job has completed with return code 0.
e
!e ```py
(import("time"),print("This code is to confuse my friends "))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
This code is to confuse my friends
Yay
Now time to find out how to import multiple modules
!e ```py
(import("time"), (import("random),print("e"))
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | File "<string>", line 1
002 | (__import__("time"), (__import__("random),print("e"))
003 | ^
004 | SyntaxError: unterminated string literal (detected at line 1)
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | File "<string>", line 1
002 | (__import__("time"), (__import__("random),print("e")))
003 | ^
004 | SyntaxError: unterminated string literal (detected at line 1)
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
e
quote over random not closed
Not esoteric tho
!r
(__import__("time"), (__import__("random"),print("e")))
It’s !e lol
!e
(__import__("time"), (__import__("random"),print("e")))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
e
Ohhh
!e ```py
(import("time"), (import("random”),print("e")))
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | File "<string>", line 1
002 | (__import__("time"), (__import__("random”),print("e")))
003 | ^
004 | SyntaxError: unterminated string literal (detected at line 1)
Remove one ) at the end
!e
(__import__("time"), (__import__("random"),print("e")))
Wait nvm
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
e
!e ```py
(import("time"), (import("random”),print("e")))
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | File "<string>", line 1
002 | (__import__("time"), (__import__("random”),print("e")))
003 | ^
004 | SyntaxError: unterminated string literal (detected at line 1)
Different “
Oh my god
!e ```py
(import(“time”), (import(“random”),print("e")))
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | File "<string>", line 1
002 | (__import__(“time”), (__import__(“random”),print("e")))
003 | ^
004 | SyntaxError: invalid character '“' (U+201C)
Yeahhh
"
“
There is a difference
You need to use the right quotes
Never knew there were different quotes
The more you know
You can’t print text with those bitwise ops or can you? @sick hound
you can deconstruct text into bytes, those bytes into an int array and those ints into bits
"
"
To really mess with someone’s mind you can also use these Chinese quotes I guess, I think they are different