Skip to content

Commit

Permalink
xdelta: initial handler for invalid xdelta target window checksums
Browse files Browse the repository at this point in the history
  • Loading branch information
imLinguin committed Nov 12, 2023
1 parent 947d074 commit 04cbb54
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 4 deletions.
5 changes: 4 additions & 1 deletion gogdl/dl/managers/task_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,10 @@ def process_writer_task_results(self, shm_cond: Condition):

if not res.success:
self.logger.fatal("Task writer failed")

if res.task.flags & generic.TaskFlag.PATCH:
# Handle full redownload?
pass

self.progress.update_bytes_written(res.written)
if res.task.old_file:
self.progress.update_bytes_read(res.task.size or 0)
Expand Down
6 changes: 4 additions & 2 deletions gogdl/dl/objects/v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,10 @@ def __init__(self):
def get(cls, manifest, old_manifest, lang: str, dlcs: list, api_handler):
if isinstance(manifest, v1.Manifest) or isinstance(old_manifest, v1.Manifest):
return None
from_build = old_manifest.data['buildId']
to_build = manifest.data['buildId']
from_build = old_manifest.data.get('buildId')
to_build = manifest.data.get('buildId')
if not from_build or not to_build:
return None
dlc_ids = [dlc["id"] for dlc in dlcs]
patch_meta = dl_utils.get_zlib_encoded(api_handler, f'{constants.GOG_CONTENT_SYSTEM}/products/{manifest.product_id}/patches?_version=4&from_build_id={from_build}&to_build_id={to_build}')[0]
if not patch_meta or patch_meta.get('error'):
Expand Down
5 changes: 5 additions & 0 deletions gogdl/xdelta/objects.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from dataclasses import dataclass
from io import IOBase, BytesIO
from typing import Optional

@dataclass
class CodeTable:
Expand Down Expand Up @@ -69,6 +70,8 @@ class Context:
cpy_len: int = 0
cpy_off: int = 0
dec_winoff: int = 0

target_buffer: Optional[bytearray] = None

def build_code_table():
table: list[Instruction] = []
Expand Down Expand Up @@ -132,3 +135,5 @@ def build_code_table():

CODE_TABLE = build_code_table()

class ChecksumMissmatch(AssertionError):
pass
14 changes: 13 additions & 1 deletion gogdl/xdelta/patcher.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from io import BytesIO
from zlib import adler32
from gogdl.xdelta import objects

# Convert stfio integer
Expand Down Expand Up @@ -126,16 +127,19 @@ def patch(source: str, patch: str, out: str):
delta_encoding_length = read_integer_stream(patch_handle)

window_length = read_integer_stream(patch_handle)
context.target_buffer = bytearray()

delta_indicator = patch_handle.read(1)[0]

add_run_data_length = read_integer_stream(patch_handle)
instructions_length = read_integer_stream(patch_handle)
addresses_length = read_integer_stream(patch_handle)

parsed_sum = 0
if adler32_sum:
checksum = patch_handle.read(4)

parsed_sum = int.from_bytes(checksum, 'big')


context.data_sec = BytesIO(patch_handle.read(add_run_data_length))
context.inst_sec = BytesIO(patch_handle.read(instructions_length))
Expand Down Expand Up @@ -164,6 +168,13 @@ def patch(source: str, patch: str, out: str):
while current2.type != objects.XD3_NOOP:
decode_halfinst(context, current2)

if adler32_sum:
calculated_sum = adler32(context.target_buffer)
if parsed_sum != calculated_sum:
raise objects.ChecksumMissmatch

context.target.write(context.target_buffer)

indicator = patch_handle.read(1)
if not len(indicator):
win_indicator = None
Expand All @@ -172,6 +183,7 @@ def patch(source: str, patch: str, out: str):
win_number += 1


dst_handle.flush()
src_handle.close()
patch_handle.close()
dst_handle.close()
Expand Down

0 comments on commit 04cbb54

Please sign in to comment.