A library that removes the __subclasses__() list from all classes.一个清除所有类的__subclasses__()列表的库。
Project description
[English | 中文]
Usage Example
By default, Python’s __subclasses__() can include almost any class. After enabling the no_subclasses library, __subclasses__() will always return an empty list, even if new classes are defined.
>>> import no_subclasses
>>> len(object.__subclasses__()) # Without no_subclasses library
313
>>> object.__subclasses__()[:5]
[<class 'type'>, <class 'async_generator'>, <class 'bytearray_iterator'>, <class 'bytearray'>, <class 'bytes_iterator'>]
>>>
>>> no_subclasses.init() # Enable no_subclasses library
>>> object.__subclasses__()
[]
>>> int.__subclasses__()
[]
>>> type.__subclasses__(type)
[]
Additionally, the library provides secure exec and eval functions, which cannot call any built-in functions or classes, nor can they be exploited by calling any class’s __subclasses__() method.
>>> from no_subclasses import init,safe_eval
>>>
>>> safe_scope = {"__builtins__":{}} # Cannot call any built-in functions
>>> attack_expr = "(1).__class__.__base__.__subclasses__()"
>>> eval(attack_expr,safe_scope) # eval before enabling no_subclasses
[<class 'type'>, <class 'async_generator'>, <class 'int'>,
<class 'bytearray_iterator'>, <class 'bytearray'>,
<class 'bytes_iterator'>, <class 'bytes'>,
<class 'PyCapsule'>,<class 'classmethod'>,...] # Contains many built-in functions, insecure
>>>
>>> init()
>>> safe_eval(attack_expr) # or eval(attack_expr,safe_scope)
[]
Detailed Usage
hack_class(cls): Clears the __subclasses__() list of a class.
hack_all_classes(start = object, ignored=()): Starting from a root class (default is object), clears the __subclasses__ list of all subclasses. ignored is a list or tuple of classes to be ignored, default is empty.
init_build_class_hook(): Modifies the built-in __build_class__ function so that executing a class statement does not modify the __subclasses__() list again, eliminating the need to re-call hack_class().
init_type_hook(): Modifies the built-in type() and type.__new__() so that calling type() or type.__new__() does not modify the __subclasses__() list again, eliminating the need to re-call hack_class(). (Requires pydetour library)
``init()``: Initializes the entire no_subclasses library, calling hack_all_classes, init_build_class_hook, and init_type_hook together. (Recommended)
Implementation Principle
The hack_class method is implemented based on the lower-level pyobject library’s get_type_subclasses and set_type_subclasses methods. The hack_all_classes method uses BFS to deeply search all subclasses and then calls hack_class on each class.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file no_subclasses-1.0.2.1.tar.gz.
File metadata
- Download URL: no_subclasses-1.0.2.1.tar.gz
- Upload date:
- Size: 5.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23e5f2acc276e59cb0f85a13c6c648ac3d25f6150e3313eb4266af5b46ecfd46
|
|
| MD5 |
90ed4cc97d32cd9a2245db7f247598bf
|
|
| BLAKE2b-256 |
cd8d308f17bdc19c5a8abc6b3df415545c97b7409d2ae5be0ed2805a024ae53d
|