java-topology/whitepaper/outreach/syncthing.md
russell@unturf.com 652608142a feat: close outreach doc gap — 276 docs (batches 11-16)
All projects with patches now have outreach docs. 276 new docs covering
CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#,
PHP, Ruby, JavaScript, Dart, Erlang, R, and more.

Outreach gap: 276 -> 0.
2026-04-15 13:57:42 -04:00

2.6 KiB
Raw Permalink Blame History

Syncthing — CWE-407 Disclosure Brief

2026-04-13 · Patch available — awaiting upstream merge

Finding

One O(n²) defect in Syncthing's file synchronization download state tracker. Block index membership checks use a slice with linear slices.Contains() instead of a map, causing quadratic behavior during large file sync. Patched.

The Defects

syncthing-0001 (PATCHED — MEDIUM): lib/model/devicedownloadstate.go

// In deviceFolderDownloadState.Has() — fires per device per block:
return slices.Contains(local.blockIndexes, index) // []int — O(B) linear scan

blockIndexes is stored as []int with slices.Contains() for O(B) lookup. Called from blockAvailabilityFromTemporaryRLocked per device per block during file sync. Total complexity per file pull: O(D × B²) where D=devices, B=blocks.

Complexity Proof

syncthing-0001: At B=500 blocks (realistic for 64MB file with 128KB block size):

  • Defective: 500 × 499/2 ≈ 124,750 comparisons per device to populate
  • Fixed: 500 map lookups (O(1) each)
  • ~250× overhead at B=500 blocks. Fires during every large file sync.

Impact

Syncthing is a widely-used open-source continuous file synchronization program with millions of installations. Large file sync (100MB+ files with 128KB blocks = 800+ blocks) across multiple devices triggers quadratic behavior in the sync hot path. Users syncing media files, VM images, or database backups between devices experience unnecessary CPU overhead during every sync operation.

The Fix

syncthing-0001: Replace []int with map[int]struct{} for O(1) membership test:

// Before — O(B) per lookup
blockIndexes []int
return slices.Contains(local.blockIndexes, index)

// After — O(1) per lookup
blockIndexes map[int]struct{}
_, found := local.blockIndexes[index]
return found

Patch

Fix available: defects/syncthing/patch/syncthing-0001-devicedownloadstate-blockindexes-linear-scan.patch

Single-file patch in lib/model/devicedownloadstate.go. Replaces slice storage with map throughout the deviceFolderFileDownloadState and deviceFolderDownloadState types.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference (syncthing/syncthing).
  2. Assess severity — fires during every large file sync across all connected devices.
  3. Coordinate a disclosure date — we are targeting 90 days from first contact.
  4. We will credit the Syncthing team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.