Skip to content

Instantly share code, notes, and snippets.

@badouralix
Created May 2, 2021 09:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save badouralix/b55bf0ad5ada2b58e04d7d6ef276c71b to your computer and use it in GitHub Desktop.
Save badouralix/b55bf0ad5ada2b58e04d7d6ef276c71b to your computer and use it in GitHub Desktop.
PoC of an interesting buggy behavior in Python.
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
PoC of an intresting buggy behavior in Python.
"""
from pprint import pprint
class Mutable:
__slots__ = ["attr"]
def __init__(self, attr=0):
self.attr = attr
def __hash__(self):
return hash((self.attr))
def __repr__(self):
return "%s(%s)" % (
self.__class__.__name__,
self.attr,
)
def change(self):
self.attr += 1
def copy(self):
return Mutable(attr=self.attr)
class Meta:
def __init__(self, mutable=None):
self.mutable = Mutable() if mutable is None else mutable
def __hash__(self):
return hash(repr(sorted(vars(self).items())))
def __repr__(self):
return "<%s.%s object at %s - %s>" % (
self.__class__.__module__,
self.__class__.__name__,
hex(id(self)),
self.mutable,
)
def change(self):
self.mutable.change()
def copy(self):
return Meta(
mutable=self.mutable,
)
def deepcopy(self):
return Meta(
mutable=self.mutable.copy(),
)
def check(d):
# print(d)
for key in d:
print(key in d)
def main():
# dic = dict()
# mut = Mutable()
# for i in range(2):
# key = Meta(mutable=mut)
# extended_key = key.copy()
# extended_key.mutable.attr = i + 1
# dic[extended_key] = key
#
# check(dic)
# dic = dict()
# mut = Mutable()
# for i in range(2):
# key = Meta(mutable=mut)
# extended_key = key.deepcopy()
# extended_key.mutable.attr = i + 1
# dic[extended_key] = key
# check(dic)
dic = dict()
key = Mutable()
dic[key] = "value"
check(dic)
key.change()
check(dic)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
PoC of an interesting buggy behavior in Python. Also works in python2.
"""
class Mutable:
__slots__ = ["attr"]
def __init__(self, attr=0):
self.attr = attr
def __hash__(self):
return hash((self.attr))
def __repr__(self):
return "%s(%s)" % (
self.__class__.__name__,
self.attr,
)
def change(self):
self.attr += 1
def check(d):
for key in d:
if key not in d:
print("%s is not consistent" % d)
return False
print("%s is consistent" % d)
return True
def main():
dic = dict()
key = Mutable()
dic[key] = "value"
check(dic) # Return True
key.change()
check(dic) # Return False
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment