[File] [PATCH] Libvirt magic fix + msetoffset continuation regression (two patches)
Vincent Mihalkovic
vmihalko at redhat.com
Mon Mar 16 16:59:53 UTC 2026
Hi Christos,
I was working on a downstream bug (RHEL-68294) for Libvirt QEMU suspend
images: when the image is saved with xz/bzip2 compression, file should
report ", compressed" in the description, but it only did so for gzip
(format field 1). The format at offset 0x1c is defined in Libvirt upstream:
https://gitlab.com/libvirt/libvirt/-/blob/master/src/qemu/qemu_saveimage_format.h
(0 = RAW, 1 = gzip, 2 = bzip2, 3 = xz, etc.). The fix is to change the
magic at 0x1c from "lelong 1" to "lelong >0" so any non-zero format is
recognized.
Reproduced output:
Expected (with both patches):
reproducer.sav: Libvirt QEMU Suspend Image, version 2, XML length
72300, running, compressed
Reported version (file 5.39): continuation lines work, but only gzip is
recognized as compressed:
reproducer.sav: Libvirt QEMU Suspend Image, version 2, XML length
72300, running
Recent upstream (HEAD, unpatched): only the first line is printed; all
continuation lines are skipped (msetoffset regression):
reproducer.sav: Libvirt QEMU Suspend Image
While debugging, I found that commit
https://github.com/file/file/commit/0a21e4bd522ac87c4c9fb8dd0f972efec2e8f7a1
("Simplify a bit argument passing. Always initialize bb in msetoffset()",
from Steve Grubb's scan-build report) added memset(bb, 0, sizeof(*bb)) (
https://github.com/file/file/blob/0a21e4bd522ac87c4c9fb8dd0f972efec2e8f7a1/src/softmagic.c#L1580)
in the continuation branch of msetoffset() (cont_level > 0). That makes bb
"initialized" for the analyzer, but in that path the caller immediately
passes bb to mget(), which does s = bb->fbuf and nbytes = bb->flen and then
reads from s via mcopy(). With bb zeroed, s is NULL and nbytes is 0, so
mget() has no data to read. Continuation magic lines (e.g. ">0x10 lelong
x") never see the file bytes and never match. Result: only the first line
of the magic block is printed; all continuation lines are skipped. So
zeroing bb fixes the uninitialized-use bug but breaks runtime behaviour for
any magic that uses continuation lines.
The correct fix for the continuation path is to initialize bb the same way
as the "normal" branch: with the file buffer, via buffer_init(bb, -1, NULL,
b->fbuf, b->flen), so mget() can read. The OFFNEGATIVE branch can keep
memset(bb, 0) as-is; the regression we see is only on the continuation path.
I'd like to propose fixing both:
1. softmagic: In msetoffset(), in the continuation branch (cont_level >
0), use buffer_init(bb, -1, NULL, b->fbuf, b->flen) instead of memset(bb,
0, sizeof(*bb)) so continuation lines work again.
2. magic: In magic/Magdir/virtual, Libvirt block, change the line at 0x1c
from "lelong 1" to "lelong >0" so xz/bzip2/etc. are reported as compressed.
Two patches are attached.
Downstream report: https://issues.redhat.com/browse/RHEL-68294
Upstream commit that introduced the regression:
https://github.com/file/file/commit/0a21e4bd522ac87c4c9fb8dd0f972efec2e8f7a1
Thanks,
Vincent Mihalkovic
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.astron.com/pipermail/file/attachments/20260316/c4fe6b44/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: file-magic.patch
Type: application/octet-stream
Size: 424 bytes
Desc: not available
URL: <https://mailman.astron.com/pipermail/file/attachments/20260316/c4fe6b44/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: file-softmagic.patch
Type: application/octet-stream
Size: 419 bytes
Desc: not available
URL: <https://mailman.astron.com/pipermail/file/attachments/20260316/c4fe6b44/attachment-0001.obj>
More information about the File
mailing list