Fix real bugs and clean up the build with -Wall -Wextra
build / build (clang, ) (push) Failing after 12s
build / build (gcc, ) (push) Failing after 9s
build / build (gcc, --enable-io-failure-emulation) (push) Failing after 8s
build / build (gcc, --enable-warnings) (push) Failing after 6s

Build: add --enable-warnings (-Wall -Wextra); the tree is now warning-free
with it, so distributions can opt in without risking a surprise -Werror
breakage from a future compiler.

Real bugs fixed (each verified by a reproducer):

- lib/io.c: open_rollback_file() read 28 bytes into char[28] with no NUL
  and then strcmp()'d it against a 28-character magic, reading one byte
  past the array. The condition was also inverted, so a *valid* rollback
  file was rejected -- but only sometimes: the missing NUL made the result
  depend on stack garbage (verified: -O0 rejects, -O2 accepts). The whole
  --save-rollback/--rollback-changes path was unreliable. Now the buffer is
  sized for the terminator, zeroed, and the comparison is `!= 0`.
  Verified end to end: save -> reopen -> restore reports "2 blocks
  restored, 0 skipped"; a random file is rejected.

- reiserfscore/reiserfslib.c, reiserfscore/journal.c: asprintf() was
  called with &fs->fs_file_name / &fs->fs_j_file_name, but those fields
  are `char *`, not `char **`. Passing a `char **` where `char *` is
  expected wrote through the wrong pointer -- silent memory corruption on
  any allocation. Fixed by using the new checked helper.

- reiserfscore/node_formats.c: `code < 0` on an unsigned parameter was
  dead code; the guard never fired.

- resize_reiserfs: missing `break` after -j made -j fall into -f, so
  "-j dev" silently also forced the operation. Sign-compare on the
  count_blocks() ternary and on count + blocks.

- lib/misc.c: strncat with bound == strlen(src) (equivalent to strcat) into
  char[256] from a char[256] dirent name -- up to 261 bytes. Replaced with
  snprintf plus an explicit fit check.

- lib/misc.c: die() used vsprintf into a fixed 1024-byte buffer.

- strncpy with bound == destination size (mkreiserfs, tune, progbar) never
  terminated; replaced with snprintf.

Allocator: drop the homegrown magic-header allocator. It wrote "_mem_begin_"
/ "mem_end" through strcpy inside the allocation, kept the size in an
`int`, and its only safety check (checkmem) was never called -- every call
site is commented out. Replaced with a size_t header that is over-aligned
via max_align_t, so malloc alignment guarantees still hold. expandmem()
now takes the old size from the header instead of a caller-supplied value
that could disagree with it.

Warnings: annotate the deliberate fallthroughs (fsck pass cascade, unit
suffix parsing, percentage parsing), fix the remaining sign-compare and
missing-field-initializer sites, and compute addresses of packed members
via char* + offsetof instead of &member.

Portability: asm/types.h -> linux/types.h, malloc.h and sys/vfs.h dropped
from includes.h (nothing used them), sys/vfs.h -> sys/statfs.h for
statfs(2).

Version: reiserfsprogs.spec said 3.6.23 while configure.ac said 3.6.25.

Remove the dead `#if 0` main() from hashes.c.

Add .github/workflows/build.yml: gcc, clang, --enable-warnings and
--enable-io-failure-emulation, each followed by a format/check/inspect
smoke test on a real image.

Verified: ./autogen.sh && ./configure --enable-warnings && make is clean
from scratch (0 warnings, 51 compile/link steps). mkreiserfs, reiserfsck
--check, debugreiserfs -S, reiserfstune -l and a real resize_reiserfs
128M -> 256M all succeed, and fsck reports the resized image clean.
This commit is contained in:
lgcosta committed 2026-11-11 22:02:38 -03:00
1 parent 41fb30313e
commit 293e6a7280
28 files changed
+258 -190

No files matched your search

+12 -12
View File
@@ -52,18 +52,18 @@ int main(int argc, char *argv[]);
* options
*/
#define OPT_INTERACTIVE 1 << 0
#define OPT_ADJUST_FILE_SIZE 1 << 1 /* not default yet */
#define OPT_QUIET 1 << 2 /* no "speed" info */
#define OPT_SILENT 1 << 3 /* no complains about found corruptions */
#define OPT_BACKGROUND 1 << 4
#define OPT_SKIP_JOURNAL 1 << 5
#define OPT_HASH_DEFINED 1 << 6
#define OPT_SAVE_PASSES_DUMP 1 << 7
#define OPT_SAVE_ROLLBACK 1 << 8
#define OPT_YES 1 << 9
#define BADBLOCKS_FILE 1 << 10
#define OPT_FORCE 1 << 11
#define OPT_INTERACTIVE 1U << 0
#define OPT_ADJUST_FILE_SIZE 1U << 1 /* not default yet */
#define OPT_QUIET 1U << 2 /* no "speed" info */
#define OPT_SILENT 1U << 3 /* no complains about found corruptions */
#define OPT_BACKGROUND 1U << 4
#define OPT_SKIP_JOURNAL 1U << 5
#define OPT_HASH_DEFINED 1U << 6
#define OPT_SAVE_PASSES_DUMP 1U << 7
#define OPT_SAVE_ROLLBACK 1U << 8
#define OPT_YES 1U << 9
#define BADBLOCKS_FILE 1U << 10
#define OPT_FORCE 1U << 11
/* pass0.c */
extern reiserfs_bitmap_t *leaves_bitmap;
+2 -1
View File
@@ -4,6 +4,7 @@
*/
#include "fsck.h"
#include "misc.h"
void erase_name(int len);
void print_name(char *name, int len);
@@ -180,7 +181,7 @@ static __u64 _look_for_lost(reiserfs_filsys_t fs, int link_lost_dirs)
(&ih->ih_key));
}
asprintf(&lost_name, "%u_%u",
xasprintf(&lost_name, "%u_%u",
get_key_dirid(&tmp_ih.ih_key),
get_key_objectid(&tmp_ih.ih_key));
+15 -9
View File
@@ -4,6 +4,7 @@
*/
#include "fsck.h"
#include "misc.h"
#include <getopt.h>
#include <sys/resource.h>
#include <sys/mman.h>
@@ -198,7 +199,7 @@ static char *parse_options(struct fsck_data *data, int argc, char *argv[])
break;
#endif
case 'd': /* --create-passes-dump */
asprintf(&data->rebuild.passes_dump_file_name, "%s",
xasprintf(&data->rebuild.passes_dump_file_name, "%s",
optarg);
data->options |= OPT_SAVE_PASSES_DUMP;
break;
@@ -208,7 +209,7 @@ static char *parse_options(struct fsck_data *data, int argc, char *argv[])
break;
case 'h': /* --hash: suppose that this hash was used on a filesystem */
asprintf(&data->rebuild.defined_hash, "%s", optarg);
xasprintf(&data->rebuild.defined_hash, "%s", optarg);
if (name2func(data->rebuild.defined_hash) == NULL)
reiserfs_panic
("reiserfsck: Unknown hash is specified: %s",
@@ -221,12 +222,12 @@ static char *parse_options(struct fsck_data *data, int argc, char *argv[])
break;
case 'R': /* preparing rollback data */
asprintf(&data->rebuild.rollback_file, "%s", optarg);
xasprintf(&data->rebuild.rollback_file, "%s", optarg);
data->options |= OPT_SAVE_ROLLBACK;
break;
case 'B': /* list of phisically corrupted blocks */
asprintf(&badblocks_file, "%s", optarg);
xasprintf(&badblocks_file, "%s", optarg);
data->options |= BADBLOCKS_FILE;
break;
@@ -916,25 +917,29 @@ static void rebuild_tree(reiserfs_filsys_t fs)
"reiserfsck --rebuild-tree started at %s"
"###########\n", ctime(&t));
/* Deliberate cascade: each pass falls into the next so that a rebuild
always runs every stage from the requested starting point on. */
switch (where_to_start_from(fs)) {
case START_FROM_THE_BEGINNING:
reset_super_block(fs);
pass_0(fs);
/* fall through */
case START_FROM_PASS_1:
reset_super_block(fs);
pass_1(fs);
/* fall through */
case START_FROM_PASS_2:
pass_2(fs);
/* fall through */
case START_FROM_SEMANTIC:
pass_3_semantic(fs);
/* fall through */
/* if --lost+found is set - link unaccessed directories to lost+found
directory */
case START_FROM_LOST_FOUND:
pass_3a_look_for_lost(fs);
/* fall through */
case START_FROM_PASS_4:
/* 4. look for unaccessed items in the leaves */
@@ -1267,7 +1272,7 @@ static int open_devices_for_rollback(char *file_name, struct fsck_data *data)
fs = getmem(sizeof(*fs));
fs->fs_dev = fd;
fs->fs_vp = data;
asprintf(&fs->fs_file_name, "%s", file_name);
xasprintf(&fs->fs_file_name, "%s", file_name);
if (data->journal_dev_name && strcmp(data->journal_dev_name, file_name)) {
fs->fs_journal_dev = open(data->journal_dev_name,
@@ -1454,7 +1459,8 @@ int main(int argc, char *argv[])
if (auto_check(fs))
break;
data->mode = FSCK_FIX_FIXABLE;
case FSCK_CHECK:
/* fall through */
case FSCK_CHECK: /* and FSCK_FIX_FIXABLE */
case FSCK_FIX_FIXABLE:
check_fs(fs);
break;
+3 -5
View File
@@ -4,6 +4,7 @@
*/
#include "fsck.h"
#include "misc.h"
/* on pass2 we take leaves which could not be inserted into tree
during pass1 and insert each item separately. It is possible that
@@ -74,7 +75,7 @@ static __u64 link_one(struct relocated *file)
struct reiserfs_key obj_key;
__u64 len = 0;
asprintf(&name, "%lu,%lu", file->old_dir_id, file->new_objectid);
xasprintf(&name, "%lu,%lu", file->old_dir_id, file->new_objectid);
set_key_dirid(&obj_key, file->old_dir_id);
set_key_objectid(&obj_key, file->new_objectid);
@@ -118,15 +119,12 @@ void linked_already(const struct reiserfs_key *new_key /*, link_func_t link_func
void link_relocated_files(void)
{
struct relocated *tmp;
int count;
count = 0;
while (relocated_list) {
link_one(relocated_list);
tmp = relocated_list;
relocated_list = relocated_list->next;
freemem(tmp);
count++;
}
}
@@ -369,7 +367,7 @@ static void put_directory_item_into_tree(struct item_head *comingih, char *item)
" badly hashed entry", i, namelen, name,
&comingih->ih_key);
asprintf(&buf, "%.*s", namelen, name);
xasprintf(&buf, "%.*s", namelen, name);
/* 1 for fsck is important: if there is no any items of this
directory in the tree yet - new item will be inserted
marked not reached */
+4 -2
View File
@@ -3,6 +3,7 @@
*/
#include "fsck.h"
#include "misc.h"
static struct reiserfs_key *trunc_links = NULL;
static __u32 links_num = 0;
@@ -366,7 +367,7 @@ start_again:
memcpy(dir_item, ih_item_body(bh, ih), get_ih_item_len(ih));
/* next item key */
if (PATH_LAST_POSITION(&path) == (B_NR_ITEMS(bh) - 1) &&
if (PATH_LAST_POSITION(&path) + 1 == B_NR_ITEMS(bh) &&
(rdkey = uget_rkey(&path)))
copy_key(key, rdkey);
else {
@@ -559,7 +560,7 @@ static int check_semantic_pass(struct reiserfs_key *key,
}
namelen = name_in_entry_length(&tmp_ih, deh, i);
asprintf(&name, "%.*s", namelen, name_in_entry(deh, i));
xasprintf(&name, "%.*s", namelen, name_in_entry(deh, i));
entry_len = entry_length(&tmp_ih, deh, i);
get_object_key(deh, &object_key, &entry_key, &tmp_ih);
@@ -634,6 +635,7 @@ static int check_semantic_pass(struct reiserfs_key *key,
("check_semantic_pass: Name \"%.*s\" in directory %K points to "
"nowhere\n", namelen, name,
&tmp_ih.ih_key);
/* fall through */
case LOOP_FOUND:
if (fsck_mode(fs) == FSCK_FIX_FIXABLE) {
reiserfs_remove_entry(fs, &entry_key);
+3 -2
View File
@@ -4,6 +4,7 @@
*/
#include "fsck.h"
#include "misc.h"
int screen_width;
static int screen_curr_pos;
@@ -639,7 +640,7 @@ static char *get_next_directory_item(struct reiserfs_key *key, /* on return this
memcpy(dir_item, ih_item_body(bh, ih), get_ih_item_len(ih));
/* next item key */
if (PATH_LAST_POSITION(&path) == (B_NR_ITEMS(bh) - 1) &&
if (PATH_LAST_POSITION(&path) + 1 == B_NR_ITEMS(bh) &&
(rdkey = uget_rkey(&path)))
copy_key(key, rdkey);
else {
@@ -923,7 +924,7 @@ start_again: /* when directory was relocated */
}
namelen = name_in_entry_length(&tmp_ih, deh, i);
asprintf(&name, "%.*s", namelen, name_in_entry(deh, i));
xasprintf(&name, "%.*s", namelen, name_in_entry(deh, i));
entry_len = entry_length(&tmp_ih, deh, i);
+2 -2
View File
@@ -13,8 +13,8 @@ static int do_items_have_the_same_type(const struct item_head *ih,
static int are_items_in_the_same_node(const struct reiserfs_path *path)
{
return (PATH_LAST_POSITION(path) <
B_NR_ITEMS(PATH_PLAST_BUFFER(path)) - 1) ? 1 : 0;
return (PATH_LAST_POSITION(path) + 1 <
B_NR_ITEMS(PATH_PLAST_BUFFER(path))) ? 1 : 0;
}
static void cut_last_unfm_pointer(struct reiserfs_path *path,