QTZPOC-20
QTZPOC-20: Enhance system robustness and test coverage across bundle processing, activity error handling, and worker operations. * Strengthen bundle reader validation with new tests for archive integrity, security vulnerabilities (e.g., path traversal, duplicate entries, special file types), and I/O error resilience. * Improve error handling and status propagation in PI Web API, MLflow, and OPC activities, including partial write scenarios and OPC session management. * Add comprehensive tests for worker startup, configuration, graceful shutdown, and Prometheus metrics server initialization. * Introduce a new utility for intelligent DataFrame debugging, summarizing large dataframes for concise logging, and refine exception chain summarization. * Update code coverage configuration to exclude @overload decorator lines.
This commit is contained in:
@@ -23,6 +23,7 @@ import hashlib
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import struct
|
||||
import unicodedata
|
||||
import zipfile
|
||||
@@ -118,6 +119,15 @@ class ZipSpec:
|
||||
traversal_entry: str | None = None
|
||||
bomb_bytes: int = 0
|
||||
extra_files: dict[str, bytes] = field(default_factory=dict)
|
||||
# name -> a raw `stat.S_IF*` mode, for an entry that is neither a symlink, a regular file nor a
|
||||
# directory (e.g. `stat.S_IFIFO`) — gate 4 must reject these on their file-type bits alone.
|
||||
special_mode_entries: dict[str, int] = field(default_factory=dict)
|
||||
# Directory entries the producer never writes (`build_zip` stores none), but a gate 5 defense
|
||||
# this repository still carries has to be exercised by something.
|
||||
directory_entries: list[str] = field(default_factory=list)
|
||||
# A file name already in `files`/`extra_files`, written a second time under the same name — two
|
||||
# archive entries claiming the same path, which only gate 5's extraction can catch.
|
||||
repeat_file: str | None = None
|
||||
|
||||
|
||||
def build_zip(spec: ZipSpec | None = None) -> bytes:
|
||||
@@ -145,6 +155,19 @@ def build_zip(spec: ZipSpec | None = None) -> bytes:
|
||||
archive.writestr(_regular_file_info(spec.traversal_entry), b'traversal\n')
|
||||
if spec.bomb_bytes:
|
||||
archive.writestr(_regular_file_info('artifacts/bomb.csv'), b'\0' * spec.bomb_bytes)
|
||||
for name, mode in spec.special_mode_entries.items():
|
||||
info = zipfile.ZipInfo(name)
|
||||
info.create_system = 3
|
||||
info.external_attr = mode << 16
|
||||
archive.writestr(info, b'')
|
||||
for name in spec.directory_entries:
|
||||
info = zipfile.ZipInfo(name if name.endswith('/') else f'{name}/')
|
||||
info.create_system = 3
|
||||
info.external_attr = (stat.S_IFDIR | 0o755) << 16
|
||||
archive.writestr(info, b'')
|
||||
if spec.repeat_file:
|
||||
content = {**spec.files, **spec.extra_files}[spec.repeat_file]
|
||||
archive.writestr(_regular_file_info(spec.repeat_file), content)
|
||||
return buffer.getvalue()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user