Reject unexpected filesystem errors in the test suite

This commit is contained in:
pancake committed 2026-10-26 21:12:56 +01:00
1 parent da793a230c
commit 2e8868fc63
7 files changed
+79 -16

No files matched your search

+10 -9
View File
@@ -62,8 +62,9 @@ Status legend: **[api]** core r_fs API, **[plugin]** a specific plugin,
"symlinked" variants (`R`, `D`, ...). In practice:
- grub plugins use `'f'` for regular files, which is not a defined constant.
- ubifs uses `'l'` for symlinks, also undefined.
- reiserfs and xfs report symlinks as `'f'`, and opening them fails
(`reiserfs-link-root.img`, `xfs-symlink-size.img`).
- reiserfs and xfs now preserve symlinks as `'l'` through the grub wrapper
(`reiserfs-link-root.img`, `xfs-symlink-size.img`); reading their targets
still needs the readlink API below.
- no plugin uses the upper-case variants.
- **Proposal:**
- define `R_FS_FILE_TYPE_SYMLINK 'l'`, `R_FS_FILE_TYPE_FIFO 'p'` and `R_FS_FILE_TYPE_SOCKET 'S'`;
@@ -157,14 +158,14 @@ Status legend: **[api]** core r_fs API, **[plugin]** a specific plugin,
| Plugin | Image | Symptom | Notes |
|---|---|---|---|
| bfs | `haiku.bfs` | `/radare2_test/gvpr`: reads stop at 2048 of 5736 bytes, and later reads return 0 | `fs_bfs_read` only looks at the block run that contains `addr` ("read from direct blocks only"). Indirect and double-indirect runs are needed |
| ext2 (grub) | `ext4_advanced.img` | mount fails | incompat flags 0x22c2: extents, 64bit, flex_bg and **metadata_csum_seed** (0x2000). grub rejects unknown incompat bits. Allow it read-only |
| ntfs | `ntfs.img` | `$Extend/$ObjId`, `$Quota` and `$Reparse` are listed but cannot be opened | these metafiles have no unnamed `$DATA` stream. Report them as special, or expose their named streams |
| ntfs | `ntfs-resident-oob.img` | `/file` cannot be opened | crafted image. Make sure the failure is a clean error |
| reiserfs | `reiserfs-link-root.img`, `reiserfs-corrupt.img` | `link` is reported as `'f'` and cannot be opened | symlink type missing (see 1.5, 1.6) |
| xfs | `xfs-symlink-size.img` | `link` is reported as `'f'` | same as above |
| bfs | `haiku.bfs` | fixed: multi-block and cross-run reads return the full file | direct runs use the same reader as directories; indirect and double-indirect runs remain unsupported |
| ext2 (grub) | `ext4_advanced.img` | fixed: the image mounts and passes read stress | 64-bit group descriptor stride and inode table addresses are supported; metadata checksum seeds are allowed for read-only access |
| ntfs | `ntfs.img` | fixed: index-view metadata is reported as special entries | named stream access remains a separate feature |
| ntfs | `ntfs-resident-oob.img` | `/file` is correctly refused | passing negative test checks the exact open failure; a crash or unrelated error fails |
| reiserfs | `reiserfs-link-root.img`, `reiserfs-corrupt.img` | fixed: `link` is reported as `'l'` | readlink support is still missing (see 1.6) |
| xfs | `xfs-symlink-size.img` | fixed: `link` is reported as `'l'` | readlink support is still missing |
| ubifs | `ubifs.img` | 174 symlinks reported as `'l'` | readlink support (1.6) |
| ubifs | `ubifs-oversize.img` | `File size (11) exceeds filesystem size (0)`, then 0 bytes are read | `leb_cnt` is 0 here. The size clamp should not use the volume size when that size is unknown |
| ubifs | `ubifs-oversize.img` | fixed: the 11-byte file reads correctly | the volume-size clamp applies only when the volume size is known |
| iso9660 | `iso.img` | level-1 names without an extension keep the dot: `LS.`, `SERVICES.` | strip the trailing `.` together with the `;1` version |
| hfs | `hfs-oobread.img` | refuses to mount | crafted image, the expected result |
| bfs | `bfs-sibling-cycle.img` | refuses to mount | crafted image, the expected result |
+1
View File
@@ -61,6 +61,7 @@ static:
./dist/static.sh
check test: $(BIN)
sh ./test/harness.sh
./test/run.sh $(TESTBINS)
install: $(BIN)
+5 -2
View File
@@ -170,8 +170,11 @@ f 19605 c960f1896b3e8434 /etc/services
from the [radare2-testbins](https://github.com/radareorg/radare2-testbins)
`fs/` directory (default `../radare2/test/bins/fs`, override with
`make check TESTBINS=...`). Each image has an expected result. Plugin bugs show
up as `XFAIL`, and when one gets fixed it shows up as `XPASS` so the table can be
updated. Set `R2FUSE_MOUNT=1` to also mount every image and compare file sizes
up as `XFAIL`, and when one gets fixed it shows up as `XPASS` and fails the run
until its expectation is updated. Malformed images pass only when they are
rejected with the expected error; crashes and timeouts always fail.
The check/stress commands return 0 on success, 1 on a failed check, and 2 if
the image cannot be opened or mounted. Set `R2FUSE_MOUNT=1` to also mount every image and compare file sizes
as seen through the kernel.
## How it works
+2
View File
@@ -57,6 +57,8 @@ executable('r2fuse',
link_args: link_args,
install: true)
test('harness', find_program('sh'), args: [meson.current_source_dir() / 'test/harness.sh'])
test('check', find_program('test/run.sh'),
args: [get_option('testbins')],
depends: [],
+48
View File
@@ -0,0 +1,48 @@
#!/bin/sh
# Exercise the runner's exit-status handling without real filesystem plugins.
set -eu
HERE=$(cd "$(dirname "$0")" && pwd)
TMP=$(mktemp -d "${TMPDIR:-/tmp}/r2fuse-harness.XXXXXX")
trap 'rm -rf "$TMP"' EXIT
mkdir "$TMP/images"
cat > "$TMP/mock" <<'EOF'
#!/bin/sh
case "$R2FUSE_TEST_STATUS" in
timeout) exec sleep 2 ;;
esac
printf '%s\n' "$R2FUSE_TEST_OUTPUT"
exit "$R2FUSE_TEST_STATUS"
EOF
chmod +x "$TMP/mock"
check() {
image=$1 status=$2 output=$3 expected=$4
: > "$TMP/images/$image"
result=0
R2FUSE="$TMP/mock" R2FUSE_MOUNT= TIMEOUT=1 \
R2FUSE_TEST_STATUS="$status" R2FUSE_TEST_OUTPUT="$output" \
sh "$HERE/run.sh" "$TMP/images" > "$TMP/output" 2>&1 || result=$?
rm -f "$TMP/images/$image"
if [ "$result" -ne "$expected" ]; then
echo "Runner regression: $image, status $status: exit $result, expected $expected"
cat "$TMP/output"
exit 1
fi
}
check ext2.img 0 'valid image' 0
check ext2.img 1 'unexpected read failure' 1
check ext2.img 2 'unexpected mount rejection' 1
check ext2.img 139 'crash' 1
check ext2.img timeout '' 1
check bfs-sibling-cycle.img 2 'malformed image rejected' 0
check bfs-sibling-cycle.img 0 'unexpected acceptance' 1
check bfs-sibling-cycle.img 1 'wrong kind of failure' 1
check bfs-sibling-cycle.img 139 'crash' 1
check ntfs-resident-oob.img 1 'FAIL /file: open failed' 0
check ntfs-resident-oob.img 1 'FAIL /other: open failed' 1
check ntfs-resident-oob.img 1 'FAIL /file: read failed' 1
check ntfs-resident-oob.img 139 'crash' 1
check ntfs-resident-oob.img 0 'unexpected acceptance' 1
echo 'OK runner rejects unexpected errors, crashes, timeouts and unexpected passes'
+2 -2
View File
@@ -12,8 +12,8 @@ iso3.img - ok
iso-joliet-rockridge.iso - ok
udf.img udf ok autodetected as iso9660
haiku.bfs - ok
ntfs.img - fail $Extend metafiles cannot be opened
ntfs-resident-oob.img - fail crafted image
ntfs.img - ok index-view metadata is reported as special files
ntfs-resident-oob.img - reject-file:/file resident value outside the MFT record
reiserfs-link-root.img - ok symlinks are reported as special files
reiserfs-corrupt.img - ok crafted image
reiserfs-name-oob.img - ok crafted image
+11 -3
View File
@@ -70,12 +70,20 @@ while read -r img fstype expect notes; do
2) res=reject ;;
*) res=crash ;;
esac
case "$expect" in
reject-file:*)
if [ "$rc" -eq 1 ] && [ "$(grep -c '^FAIL ' "$TMP/out")" -eq 1 ] \
&& grep -Fxq "FAIL ${expect#reject-file:}: open failed" "$TMP/out"; then
res=$expect
fi
;;
esac
summary=$(tail -n 1 "$TMP/out")
if [ "$res" = "$expect" ]; then
if [ "$res" != crash ] && [ "$res" = "$expect" ]; then
if [ "$res" = ok ]; then
echo "OK $img: $summary"; pass=$((pass + 1))
elif [ "$res" = reject ]; then
echo "OK $img: rejected malformed image"; pass=$((pass + 1))
elif [ "$res" != fail ]; then
echo "OK $img: rejected malformed image or file"; pass=$((pass + 1))
else
echo "XFAIL $img: $notes"; xfail=$((xfail + 1))
fi