From 7e7632ad3c1d2bed45a0e39a226d63cb6e8ec1de Mon Sep 17 00:00:00 2001 From: Ed Zynda Date: Sun, 22 Mar 2026 19:36:31 +0300 Subject: [PATCH] fix(session): use bufio.Reader instead of Scanner to handle long lines Replace bufio.Scanner with bufio.Reader in OpenTreeSession to avoid 64KB line length limit. Scanner silently truncates long lines which can corrupt session data. Reader handles arbitrary line lengths properly. --- internal/session/tree_manager.go | 34 ++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/internal/session/tree_manager.go b/internal/session/tree_manager.go index b636ac53..c72280bf 100644 --- a/internal/session/tree_manager.go +++ b/internal/session/tree_manager.go @@ -4,6 +4,7 @@ import ( "bufio" "encoding/json" "fmt" + "io" "os" "path/filepath" "strings" @@ -128,10 +129,34 @@ func OpenTreeSession(path string) (*TreeManager, error) { filePath: path, } - scanner := bufio.NewScanner(strings.NewReader(string(data))) + reader := bufio.NewReader(strings.NewReader(string(data))) lineNum := 0 - for scanner.Scan() { - line := scanner.Text() + for { + line, err := reader.ReadString('\n') + if err != nil { + if err == io.EOF { + // Process the last line if it's not empty + if strings.TrimSpace(line) != "" { + lineNum++ + entry, err := UnmarshalEntry([]byte(line)) + if err != nil { + return nil, fmt.Errorf("line %d: %w", lineNum, err) + } + if lineNum == 1 { + h, ok := entry.(*SessionHeader) + if !ok { + return nil, fmt.Errorf("first line must be a session header, got %T", entry) + } + tm.header = *h + } else { + tm.addEntryToIndex(entry) + } + } + break + } + return nil, fmt.Errorf("failed to read session file: %w", err) + } + if strings.TrimSpace(line) == "" { continue } @@ -153,9 +178,6 @@ func OpenTreeSession(path string) (*TreeManager, error) { tm.addEntryToIndex(entry) } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("failed to scan session file: %w", err) - } // Set leaf to the last entry. if len(tm.entries) > 0 {