From 8c14c50f3578e56cffb5480e6ee630b37808db7d Mon Sep 17 00:00:00 2001 From: JudahJL Date: Tue, 2 Dec 2025 22:01:26 +0530 Subject: [PATCH] Fix line ending handling to enable crash log processing Without this fix, crash log files were not being processed at all due to incorrect line ending detection. The read_file() method failed to identify section markers when line endings differed from expected format. - Add get_line_ending() to preserve original line endings (CRLF/LF/CR) - Refactor read_file() to use splitlines(keepends=True) for proper parsing - Update add_name() to preserve line endings instead of forcing \n - Handle all line ending variants for PROBABLE CALL STACK and REGISTERS markers --- crashlogtools/crashlogutil.py | 65 +++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/crashlogtools/crashlogutil.py b/crashlogtools/crashlogutil.py index b418e8f..f612413 100644 --- a/crashlogtools/crashlogutil.py +++ b/crashlogtools/crashlogutil.py @@ -77,13 +77,15 @@ def add_name(line: bytes, id_lookup: Dict[int, bytes], width: int) -> bytes: if not match: return line + ending = CrashLogProcessor.get_line_ending(line) + stack_frame = match.group(0) name = id_lookup.get(int(match.group("id"))) if not name: - return stack_frame + b"\n" + return stack_frame + ending name = name.rstrip(b"_*") - return stack_frame.ljust(width, b' ') + name + b"\n" + return stack_frame.ljust(width, b' ') + name + ending def lookup_ids(self, id_list: List[int]) -> Dict[int, bytes]: database = self.get_database_path() @@ -98,6 +100,16 @@ def lookup_ids(self, id_list: List[int]) -> Dict[int, bytes]: lookup[addr_id] = name return lookup + @staticmethod + def get_line_ending(line: bytes) -> bytes: + if line.endswith(b"\r\n"): + return b"\r\n" + if line.endswith(b"\n"): + return b"\n" + if line.endswith(b"\r"): + return b"\r" + return b"" + class CrashLog: def __init__(self, path: Path): @@ -125,35 +137,28 @@ def write_file(self, path: Path) -> None: f.writelines(self.post_call_stack) def read_file(self, path: Path) -> None: - with path.open("rb") as f: - while True: - line = f.readline() - if not line: - return - - self.pre_call_stack.append(line) - if line == b"PROBABLE CALL STACK:\n": - break - - while True: - line = f.readline() - if not line: - return - - if line == b"\n": - break - elif line == b"REGISTERS:\n": - self.post_call_stack.append(b"\n") - break - - self.call_stack.append(line) - - while True: + data = path.read_bytes() + lines = data.splitlines(keepends=True) + + it = iter(lines) + + for line in it: + self.pre_call_stack.append(line) + if line in (b"PROBABLE CALL STACK:\n", b"PROBABLE CALL STACK:\r\n", b"PROBABLE CALL STACK:\r",): + break + else: + return + + for line in it: + if line.strip() == b"": + break + if line in (b"REGISTERS:\n", b"REGISTERS:\r\n", b"REGISTERS:\r"): self.post_call_stack.append(line) + break + self.call_stack.append(line) - line = f.readline() - if not line: - return + for line in it: + self.post_call_stack.append(line) class IdScanner: @@ -184,4 +189,4 @@ def find(self, addr_id: int) -> Optional[bytes]: return None self.nextLine = self.f.readline() - return None \ No newline at end of file + return None