Skip to content

squashfs: handle images with no fragment or xattr table#413

Merged
deitch merged 1 commit into
diskfs:masterfrom
maximilize:squashfs-absent-tables
Jul 10, 2026
Merged

squashfs: handle images with no fragment or xattr table#413
deitch merged 1 commit into
diskfs:masterfrom
maximilize:squashfs-absent-tables

Conversation

@maximilize

Copy link
Copy Markdown
Contributor

Problem

The squashfs reader fails on valid images written by squashfs-tools-ng that omit optional tables. Two independent failures, both reproducible with a minimal image (gensquashfs -D <empty-dir> out.sqfs):

  • No fragment table (fragmentCount == 0): readFragmentTable reads unconditionally, but fragmentTableStart holds the 0xffffffffffffffff "not present" sentinel, so ReadAt seeks to offset -1 and fails with error reading fragment table index: invalid seek position.
  • No xattr table (NO_XATTRS flag): directoryEntryFromInode calls fs.xattrs.find(...) when an inode advertises an xattr index, but fs.xattrs is nil, causing a nil-pointer panic in (*xAttrTable).find (xattr.go:46).

Fix

Two guards, mirroring the "absent optional table" handling already done when the superblock is parsed (!s.noXattrs && s.xattrTableStart != 0xffffffffffffffff):

  • skip reading the fragment table when fragmentCount == 0;
  • skip the xattr lookup when fs.xattrs == nil.

Tests

Added two internal regression tests (TestReadFragmentTableNoFragments and TestDirectoryEntryFromInodeNilXattrTable), both failing before / passing after. Full filesystem/squashfs suite passes and go vet is clean.

Verified end-to-end through rclone's archive backend (which uses this reader): the two images from rclone/rclone#9004 that previously errored / panicked (a single empty directory, and a real squashfs-tools-ng Windows image) now list correctly.

squashfs-tools-ng writes valid images that omit the fragment table (e.g. a
single empty directory, or with -no-tail-packing) and/or the xattr table
(the NO_XATTRS superblock flag). The reader mishandled both:

- readFragmentTable read the table even when fragmentCount == 0. In that
  case fragmentTableStart holds the 0xffff... "not present" sentinel, so the
  ReadAt seeks to offset -1 and fails with "invalid seek position".
- directoryEntryFromInode dereferenced fs.xattrs when an inode advertised an
  xattr index while the image had no xattr table (fs.xattrs == nil), causing
  a nil-pointer panic in (*xAttrTable).find.

Guard both: return early for an absent fragment table, and skip the xattr
lookup when the table is nil. Adds regression tests for both paths.

Surfaced via rclone (rclone/rclone#9004), which uses this reader for its
archive backend; both a single-empty-dir image and a real squashfs-tools-ng
image now list correctly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: maximilize <max@maxmax.ch>

@deitch deitch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid catch. I feel like this shouldn't be possible, but it is, so catching it is correct.

@deitch
deitch merged commit 6793ed7 into diskfs:master Jul 10, 2026
20 checks passed
maximilize added a commit to maximilize/rclone that referenced this pull request Jul 21, 2026
Bump go-diskfs to v1.9.4, which contains diskfs/go-diskfs#413 handling
squashfs images that have no fragment table or no xattr table. On v1.9.3
these images fail to list at all (ReadDir errors inside the library).

Adapt the backend to the v1.9.4 io/fs API: ReadDir now returns
io/fs.DirEntry (metadata via DirEntry.Info), and files are opened via
FileSystem.OpenFile instead of the removed FileStat.Open. The path
conversion added in c10eb47 (toIOFS) is reused.

Add a regression test with two such images as committed fixtures - an
empty directory with no fragment table, and a tree built with NO_XATTRS
- since mksquashfs cannot reproduce these layouts.

Fixes rclone#9004
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants