Identify archives by content before file name

An archive renamed to another extension, such as a .tar.gz renamed to
.zip, was read as a zip inside a gzip stream and failed with "input type
must be an io.ReaderAt and io.Seeker". The format is now taken from the
contents first, and the file name is only used when they are not
recognized.

Fixes pterodactyl/panel#5728
This commit is contained in:
dualfroz committed 2026-10-13 22:47:20 +02:00
1 parent d8cb044658
commit e7bb19d447
2 files changed
+41 -2

No files matched your search

+27
View File
@@ -143,3 +143,30 @@ func TestDecompressZipSymlinkEntry(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "target.txt", target)
}
// An archive created by the compress endpoint and renamed to a different
// extension is still read as the format it actually is.
func TestDecompressRenamedArchive(t *testing.T) {
fs, rfs := NewFs()
t.Cleanup(func() { _ = os.RemoveAll(rfs.root) })
fs.SetDiskLimit(1 << 20)
require.NoError(t, fs.CreateDirectory("source", "/"))
require.NoError(t, rfs.CreateServerFileFromString("source/file.txt", "hello"))
st, err := fs.CompressFiles("/", []string{"source"})
require.NoError(t, err)
require.NoError(t, fs.Rename(st.Name(), "renamed.zip"))
require.NoError(t, os.RemoveAll(filepath.Join(rfs.root, "server", "source")))
// The formats matching an archive are tried in random order, so a single
// attempt can pass by chance.
for i := 0; i < 10; i++ {
require.NoError(t, fs.SpaceAvailableForDecompression(context.Background(), "/", "renamed.zip"))
require.NoError(t, fs.DecompressFile(context.Background(), "/", "renamed.zip"))
}
got, err := os.ReadFile(filepath.Join(rfs.root, "server", "source", "file.txt"))
require.NoError(t, err)
assert.Equal(t, "hello", string(got))
}