Apply sanitize string cc to all messages that need it

This commit is contained in:
ChillerDragon 2023-04-07 13:33:08 +02:00
parent 3df2a7fb12
commit 7dfaeda45f
17 changed files with 85 additions and 85 deletions

View file

@ -5,6 +5,22 @@ import json
from typing import TypedDict, Literal, Optional, Dict, Union
KIND = Literal[ \
'int32', \
'tick', \
'string', \
'raw', \
'sha256', \
'data', \
'rest', \
'enum', \
'boolean', \
'tune_param', \
'snapshot_object', \
'array', \
'flags', \
'optional']
class ConstantJson(TypedDict):
name: list[str]
type: str
@ -19,41 +35,11 @@ class NetEnumJson(TypedDict):
values: list[NetEnumValuesJson]
class InnerNetMessageMemberTypeJson(TypedDict):
# TODO: define this literal as type
# so it can be reused
kind: Literal[ \
'int32', \
'tick', \
'string', \
'raw', \
'sha256', \
'data', \
'rest', \
'enum', \
'boolean', \
'tune_param', \
'snapshot_object', \
'array', \
'flags', \
'optional']
kind: KIND
disallow_cc: bool
class NetMessageMemberTypeJson(TypedDict):
kind: Literal[ \
'int32', \
'tick', \
'string', \
'raw', \
'sha256', \
'data', \
'rest', \
'enum', \
'boolean', \
'tune_param', \
'snapshot_object', \
'array', \
'flags', \
'optional']
kind: KIND
inner: InnerNetMessageMemberTypeJson
disallow_cc: bool
@ -172,7 +158,7 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
# {'name': ['message'], 'type': {'kind': 'string', 'disallow_cc': False}}
ftype = 'int'
default = '-1'
if member['type']['kind'] == 'string': # TODO: sanitize cc
if member['type']['kind'] == 'string':
ftype = 'str'
default = "'default'"
elif member['type']['kind'] in \
@ -204,7 +190,7 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
ftype = 'int'
default = '0'
elif member['type']['kind'] == 'optional':
if member['type']['inner']['kind'] == 'string': # TODO: sanitize cc
if member['type']['inner']['kind'] == 'string':
ftype = 'str'
default = "''"
elif member['type']['inner']['kind'] in ('int32', 'tick'):
@ -251,7 +237,7 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
elif member['type']['kind'] == 'flags': # TODO: think about flags
ftype = 'int'
elif member['type']['kind'] == 'optional':
if member['type']['inner']['kind'] == 'string': # TODO: sanitize cc
if member['type']['inner']['kind'] == 'string':
ftype = 'str'
elif member['type']['inner']['kind'] in ('int32', 'tick'):
ftype = 'int'
@ -271,8 +257,11 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
for member in msg['members']:
# {'name': ['message'], 'type': {'kind': 'string', 'disallow_cc': False}}
unpacker = 'int()'
if member['type']['kind'] == 'string': # TODO: sanitize cc
unpacker = 'str()'
if member['type']['kind'] == 'string':
if member['type']['disallow_cc']:
unpacker = 'str(SANITIZE_CC)'
else:
unpacker = 'str()'
elif member['type']['kind'] in \
('raw', 'sha256', 'rest', 'data'): # TODO: data has a size field
unpacker = 'raw()'
@ -295,10 +284,14 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
elif member['type']['kind'] == 'optional':
# TODO: unpacker should not crash on missing optional fields
# check how tw code does it and be smart here
if member['type']['inner']['kind'] == 'string': # TODO: sanitize cc
unpacker = 'str() # TODO: this can fail for optionals'
if member['type']['inner']['kind'] == 'string':
if member['type']['inner']['disallow_cc']:
unpacker = 'str(SANITIZE_CC)'
unpacker += ' # TODO: optionals'
else:
unpacker = 'str() # TODO: optionals'
elif member['type']['inner']['kind'] in ('int32', 'tick'):
unpacker = 'int() # TODO: this can fail for optionals'
unpacker = 'int() # TODO: optionals'
else:
raise ValueError(f"Error: unknown type {member['type']}")
name = name_to_snake(member["name"])
@ -311,8 +304,10 @@ def generate_msg(msg: NetMessageJson, game: Literal['game', 'system']) -> None:
def get_dependencies(msg: NetMessageJson) -> str:
packer_deps: list[str] = []
for member in msg['members']:
if member['type']['kind'] == 'string': # TODO: sanitize cc
if member['type']['kind'] == 'string':
packer_deps.append('pack_str')
if member['type']['disallow_cc']:
packer_deps.append('SANITIZE_CC')
elif member['type']['kind'] in \
('raw', 'sha256', 'rest', 'data'): # TODO: data has a size field
pass
@ -335,6 +330,8 @@ def get_dependencies(msg: NetMessageJson) -> str:
elif member['type']['kind'] == 'optional':
if member['type']['inner']['kind'] == 'string':
packer_deps.append('pack_str')
if member['type']['inner']['disallow_cc']:
packer_deps.append('SANITIZE_CC')
elif member['type']['inner']['kind'] in ('int32', 'tick'):
packer_deps.append('pack_int')
else:
@ -348,7 +345,7 @@ def pack_field(member: NetMessageMemberJson) -> str:
name: str = name_to_snake(member["name"])
field: str = f'self.{name}'
packer = 'int'
if member['type']['kind'] == 'string': # TODO: sanitize cc
if member['type']['kind'] == 'string':
packer = 'str'
elif member['type']['kind'] in \
('raw', 'sha256', 'rest', 'data'): # TODO: data has a size field
@ -374,7 +371,7 @@ def pack_field(member: NetMessageMemberJson) -> str:
packer = 'int'
# TODO: unpacker should allow not packing optional fields
# check how tw code does it and be smart here
if member['type']['inner']['kind'] == 'string': # TODO: sanitize cc
if member['type']['inner']['kind'] == 'string':
packer = 'str'
elif member['type']['inner']['kind'] in ('int32', 'tick'):
packer = 'int'

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgClCallVote(PrettyPrint):
def __init__(
@ -27,9 +27,9 @@ class MsgClCallVote(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.type = unpacker.get_str()
self.value = unpacker.get_str()
self.reason = unpacker.get_str()
self.type = unpacker.get_str(SANITIZE_CC)
self.value = unpacker.get_str(SANITIZE_CC)
self.reason = unpacker.get_str(SANITIZE_CC)
self.force = unpacker.get_int() == 1
return True

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_str
from twnet_parser.packer import SANITIZE_CC, pack_str
class MsgClCommand(PrettyPrint):
def __init__(
@ -23,8 +23,8 @@ class MsgClCommand(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.name = unpacker.get_str()
self.arguments = unpacker.get_str()
self.name = unpacker.get_str(SANITIZE_CC)
self.arguments = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgClSay(PrettyPrint):
def __init__(
@ -27,7 +27,7 @@ class MsgClSay(PrettyPrint):
unpacker = Unpacker(data)
self.mode = unpacker.get_int() # TODO: this is a enum
self.target = unpacker.get_int()
self.message = unpacker.get_str()
self.message = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgClStartInfo(PrettyPrint):
def __init__(
@ -31,8 +31,8 @@ class MsgClStartInfo(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.name = unpacker.get_str()
self.clan = unpacker.get_str()
self.name = unpacker.get_str(SANITIZE_CC)
self.clan = unpacker.get_str(SANITIZE_CC)
self.country = unpacker.get_int()
self.skin_part_names = unpacker.get_int() # TODO: this is an array
self.use_custom_colors = unpacker.get_int() # TODO: this is an array

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgDeClientEnter(PrettyPrint):
def __init__(
@ -25,7 +25,7 @@ class MsgDeClientEnter(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.name = unpacker.get_str()
self.name = unpacker.get_str(SANITIZE_CC)
self.client_id = unpacker.get_int()
self.team = unpacker.get_int() # TODO: this is a enum
return True

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgDeClientLeave(PrettyPrint):
def __init__(
@ -25,9 +25,9 @@ class MsgDeClientLeave(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.name = unpacker.get_str()
self.name = unpacker.get_str(SANITIZE_CC)
self.client_id = unpacker.get_int()
self.reason = unpacker.get_str()
self.reason = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgSvChat(PrettyPrint):
def __init__(
@ -30,7 +30,7 @@ class MsgSvChat(PrettyPrint):
self.mode = unpacker.get_int() # TODO: this is a enum
self.client_id = unpacker.get_int()
self.target_id = unpacker.get_int()
self.message = unpacker.get_str()
self.message = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgSvClientDrop(PrettyPrint):
def __init__(
@ -26,7 +26,7 @@ class MsgSvClientDrop(PrettyPrint):
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.client_id = unpacker.get_int()
self.reason = unpacker.get_str()
self.reason = unpacker.get_str(SANITIZE_CC)
self.silent = unpacker.get_int() == 1
return True

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgSvClientInfo(PrettyPrint):
def __init__(
@ -42,8 +42,8 @@ class MsgSvClientInfo(PrettyPrint):
self.client_id = unpacker.get_int()
self.local = unpacker.get_int() == 1
self.team = unpacker.get_int() # TODO: this is a enum
self.name = unpacker.get_str()
self.clan = unpacker.get_str()
self.name = unpacker.get_str(SANITIZE_CC)
self.clan = unpacker.get_str(SANITIZE_CC)
self.country = unpacker.get_int()
self.skin_part_names = unpacker.get_int() # TODO: this is an array
self.use_custom_colors = unpacker.get_int() # TODO: this is an array

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_str
from twnet_parser.packer import SANITIZE_CC, pack_str
class MsgSvCommandInfo(PrettyPrint):
def __init__(
@ -25,9 +25,9 @@ class MsgSvCommandInfo(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.name = unpacker.get_str()
self.args_format = unpacker.get_str()
self.help_text = unpacker.get_str()
self.name = unpacker.get_str(SANITIZE_CC)
self.args_format = unpacker.get_str(SANITIZE_CC)
self.help_text = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_str
from twnet_parser.packer import SANITIZE_CC, pack_str
class MsgSvCommandInfoRemove(PrettyPrint):
def __init__(
@ -21,7 +21,7 @@ class MsgSvCommandInfoRemove(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.name = unpacker.get_str()
self.name = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_str
from twnet_parser.packer import SANITIZE_CC, pack_str
class MsgSvVoteOptionAdd(PrettyPrint):
def __init__(
@ -21,7 +21,7 @@ class MsgSvVoteOptionAdd(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.description = unpacker.get_str()
self.description = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_str
from twnet_parser.packer import SANITIZE_CC, pack_str
class MsgSvVoteOptionRemove(PrettyPrint):
def __init__(
@ -21,7 +21,7 @@ class MsgSvVoteOptionRemove(PrettyPrint):
# NOT the chunk header and NOT the message id
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.description = unpacker.get_str()
self.description = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgSvVoteSet(PrettyPrint):
def __init__(
@ -32,8 +32,8 @@ class MsgSvVoteSet(PrettyPrint):
self.client_id = unpacker.get_int()
self.type = unpacker.get_int() # TODO: this is a enum
self.timeout = unpacker.get_int()
self.description = unpacker.get_str()
self.reason = unpacker.get_str()
self.description = unpacker.get_str(SANITIZE_CC)
self.reason = unpacker.get_str(SANITIZE_CC)
return True
def pack(self) -> bytes:

View file

@ -3,7 +3,7 @@
from twnet_parser.pretty_print import PrettyPrint
from twnet_parser.packer import Unpacker
from twnet_parser.chunk_header import ChunkHeader
from twnet_parser.packer import pack_int, pack_str
from twnet_parser.packer import SANITIZE_CC, pack_int, pack_str
class MsgInfo(PrettyPrint):
def __init__(
@ -26,8 +26,8 @@ class MsgInfo(PrettyPrint):
def unpack(self, data: bytes) -> bool:
unpacker = Unpacker(data)
self.version = unpacker.get_str()
self.password = unpacker.get_str() # TODO: this can fail for optionals
self.client_version = unpacker.get_int() # TODO: this can fail for optionals
self.password = unpacker.get_str(SANITIZE_CC) # TODO: optionals
self.client_version = unpacker.get_int() # TODO: optionals
return True
def pack(self) -> bytes:

View file

@ -1,6 +1,6 @@
#!/usr/bin/env python
from typing import Literal, Final
from typing import Final
# Before chaning the current packer code to extend it
# Consider having two packers
@ -80,7 +80,10 @@ class Unpacker():
# If there is nothing from the python standard
# this might be worth writing in Cython
# external C or rust
def get_str(self, sanitize: Literal[0,1,2,3] = 1) -> str:
# TODO: make literals work currently passing in SANITIZE as arg
# to unpacker.get_str() does not work because its not a literal ._.
# def get_str(self, sanitize: Literal[0,1,2,3] = 1) -> str:
def get_str(self, sanitize: int = SANITIZE) -> str:
str_end: int = self.data().find(b'\x00')
res: bytes = self.data()[:str_end]
self.idx += str_end + 1