diff --git a/addons/source-python/packages/source-python/__init__.py b/addons/source-python/packages/source-python/__init__.py old mode 100644 new mode 100755 index 5ca9588e5..29a1b4739 --- a/addons/source-python/packages/source-python/__init__.py +++ b/addons/source-python/packages/source-python/__init__.py @@ -83,6 +83,7 @@ def load(): setup_logging() setup_exception_hooks() setup_data_update() + setup_check_signatures() setup_translations() setup_data() setup_global_pointers() @@ -136,6 +137,69 @@ def setup_data_update(): _sp_logger.log_exception( 'An error occured during the data update.', exc_info=True) +def setup_check_signatures(): + """Setup check signatures.""" + _sp_logger.log_debug('Checking data signatures...') + + # Python Imports + from warnings import warn + # Source.Python Imports + from memory.helpers import check_type_signature_from_file + from memory.helpers import check_pipe_signature_from_file + from paths import SP_DATA_PATH + + # iterate over SP_DATA_PATH / 'entities' and extract all files + files = set(SP_DATA_PATH / 'entities' / file.name for file in + (SP_DATA_PATH / 'entities').walkfiles('*.ini')) + + # add CBaseClient. + files.add(SP_DATA_PATH / 'client' / 'CBaseClient.ini') + + # add CBaseEntityOutput. + files.add(SP_DATA_PATH / 'entity_output' / 'CBaseEntityOutput.ini') + + class_warn = False + + # check the class type signatures. + for file in files: + for name, identifier in check_type_signature_from_file(file): + if not class_warn: + warn( + 'Invalid signature detected in class data, ' + 'specific function will not work.' + ) + class_warn = True + _sp_logger.log_warning( + 'Invalid signature detected.\n' + 'Name: {0}\nSignature: {1}\nFile: {2}\n'.format( + name, + ' '.join("{:02X}".format(i) for i in identifier), + file + ) + ) + + # check the global pointers signature + file = SP_DATA_PATH / 'memory' / 'global_pointers.ini' + + gp_warn = False + + for name, identifier in check_pipe_signature_from_file(file): + if not gp_warn: + warn( + 'Invalid signature detected in global pointers data, ' + 'may cause problems with Source.Python operation.' + ) + gp_warn = True + + _sp_logger.log_warning( + 'Invalid signature detected.\n' + 'Name: {0}\nSignature: {1}\nFile: {2}\n'.format( + name, + ' '.join("{:02X}".format(i) for i in identifier), + file + ) + ) + def setup_data(): """Setup data.""" _sp_logger.log_debug('Setting up data...') diff --git a/addons/source-python/packages/source-python/memory/helpers.py b/addons/source-python/packages/source-python/memory/helpers.py index 4c0ba2177..c845fb455 100755 --- a/addons/source-python/packages/source-python/memory/helpers.py +++ b/addons/source-python/packages/source-python/memory/helpers.py @@ -11,6 +11,7 @@ # Source.Python # Core +from core import GameConfigObj from core import PLATFORM # Memory from memory import Convention @@ -18,6 +19,7 @@ from memory import Function from memory import Pointer from memory import TYPE_SIZES +from memory import find_binary from memory import make_object @@ -30,6 +32,8 @@ 'MemberFunction', 'NO_DEFAULT', 'Type', + 'check_pipe_signature_from_file', + 'check_type_signature_from_file', 'parse_data', ) @@ -404,6 +408,85 @@ def parse_data(manager, raw_data, keys): yield (name, temp_data) +def check_type_signature_from_file(file): + """Checks if the data signatures are valid.""" + raw_data = GameConfigObj(file) + + # get the binary name from the data(defaults to server if not present) + _binary = Key.as_str(None, raw_data.get( + Key.BINARY + '_' + PLATFORM, raw_data.get(Key.BINARY, 'server'))) + _srv_check = Key.as_bool(None, raw_data.get( + Key.SRV_CHECK + '_' + PLATFORM, raw_data.get(Key.SRV_CHECK, 'True'))) + + key = Key.IDENTIFIER + binary = None + + for method, default in (('function', NO_DEFAULT), ): + for name, data in raw_data.get(method, {}).items(): + identifier = data.get(key + '_' + PLATFORM, data.get(key, default)) + + # ignore identifier + if identifier is None: + continue + + # if the identifier is NO_DEFAULT, the key is obviously missing + if identifier is NO_DEFAULT: + raise KeyError( + 'Missing identifier for "{0}".\nFile: {1}'.format( + name, file)) + + if binary is None: + try: + binary = find_binary(_binary, _srv_check) + except OSError as error: + print(error) + raise ValueError( + 'Could not find the binary.\nFile: {0}'.format(file)) + + try: + identifier = Key.as_identifier(None, identifier) + binary[identifier] + except ValueError: + yield (name, identifier) + +def check_pipe_signature_from_file(file): + """Checks if the data signatures are valid.""" + raw_data = GameConfigObj(file) + + key = Key.IDENTIFIER + + for name, data in raw_data.items(): + identifier = data.get(key + '_' + PLATFORM, data.get(key, NO_DEFAULT)) + + # if the identifier is NO_DEFAULT, the key is obviously missing + if identifier is NO_DEFAULT: + raise KeyError( + 'Missing identifier for "{0}".\nFile: {1}'.format( + name, file)) + + _binary = Key.as_str(None, data.get( + Key.BINARY + '_' + PLATFORM, data.get(Key.BINARY, NO_DEFAULT))) + if _binary is NO_DEFAULT: + raise KeyError( + 'Missing binary for "{0}".\nFile: {1}'.format( + name, file)) + + _srv_check = Key.as_bool(None, data.get( + Key.SRV_CHECK + '_' + PLATFORM, data.get(Key.SRV_CHECK, 'True'))) + + try: + binary = find_binary(_binary, _srv_check) + except OSError as error: + print(error) + raise ValueError( + 'Could not find the binary.\nFile: {0}'.format(file)) + + try: + identifier = Key.as_identifier(None, identifier) + binary[identifier] + except ValueError: + yield (name, identifier) + # Use this as a default value if the key is not allowed to have a default # value NO_DEFAULT = object()
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: