diff --git a/src/controller/config_repl.c b/src/controller/config_repl.c index 5b01a45f..dbe10f25 100644 --- a/src/controller/config_repl.c +++ b/src/controller/config_repl.c @@ -169,8 +169,11 @@ static int scan_latest_committed_marker(const char *wal_path, for (int si = 0; si < nseg; si++) { char seg_path[4096]; + /* %.*s bounds wal_path so "seg-<16 hex>.wal" (26 bytes) always fits */ snprintf(seg_path, sizeof(seg_path), - "%s/seg-%016" PRIx64 ".wal", wal_path, seg_lsns[si]); + "%.*s/seg-%016" PRIx64 ".wal", + (int)(sizeof(seg_path) - sizeof("/seg-0000000000000000.wal")), + wal_path, seg_lsns[si]); int fd = open(seg_path, O_RDONLY); if (fd < 0) continue; @@ -280,7 +283,11 @@ static int local_config_sha256(cluster_t *c, uint8_t out_sha[32]) /* Resolve the current locally-held versioned config file. */ char conf_dir[4096]; - snprintf(conf_dir, sizeof(conf_dir), "%s/%s", mc->workdir, mc->name); + /* Width-limited %.*s keeps workdir/name within conf_dir so the fixed + * "/conf/" tail provably fits path (4096+256) downstream. */ + snprintf(conf_dir, sizeof(conf_dir), "%.*s/%.*s", + (int)(sizeof(conf_dir) / 2), mc->workdir, + (int)(sizeof(conf_dir) / 2 - 2), mc->name); char fname[256] = {0}; int rc = conf_read_current_filename(conf_dir, fname, sizeof(fname)); @@ -288,7 +295,9 @@ static int local_config_sha256(cluster_t *c, uint8_t out_sha[32]) return -ENOENT; /* no local bytes yet — caller fences + retries */ char path[4352]; - snprintf(path, sizeof(path), "%s/conf/%s", conf_dir, fname); + snprintf(path, sizeof(path), "%.*s/conf/%.*s", + (int)(sizeof(path) - sizeof("/conf/") - 256), conf_dir, 256, + fname); uint8_t *bytes = NULL; size_t blen = 0; @@ -648,10 +657,12 @@ int load_primary_config(cluster_t *c) * fired near the retire step, not merely around that step alone. */ mylock_lock(&myconf->lock); - /* Build conf dir path: / */ + /* Build conf dir path: / (width-limited so the fixed + * "/conf/" tail provably fits downstream path buffers). */ char conf_dir[4096]; - snprintf(conf_dir, sizeof(conf_dir), "%s/%s", - myconf->workdir, myconf->name); + snprintf(conf_dir, sizeof(conf_dir), "%.*s/%.*s", + (int)(sizeof(conf_dir) / 2), myconf->workdir, + (int)(sizeof(conf_dir) / 2 - 2), myconf->name); /* Resolve conf/current → versioned filename */ char fname[256] = {0}; @@ -762,7 +773,7 @@ int load_primary_config(cluster_t *c) static void make_conf_dir(const char *workdir, char *out, size_t sz) { - snprintf(out, sz, "%s/conf", workdir); + snprintf(out, sz, "%.*s/conf", (int)(sz - sizeof("/conf")), workdir); } static void bytes_to_hex(const uint8_t *b, size_t n, char *out) @@ -780,7 +791,8 @@ static void bytes_to_hex(const uint8_t *b, size_t n, char *out) int conf_read_current_filename(const char *workdir, char *out, size_t outsz) { char head_path[4096]; - snprintf(head_path, sizeof(head_path), "%s/conf/current", workdir); + snprintf(head_path, sizeof(head_path), "%.*s/conf/current", + (int)(sizeof(head_path) - sizeof("/conf/current")), workdir); FILE *f = fopen(head_path, "r"); if (!f) @@ -822,10 +834,13 @@ int conf_read_current_filename(const char *workdir, char *out, size_t outsz) int conf_save_config(myconf_t *myconf, const uint8_t *bytes, size_t len, const uint8_t sha256[32]) { - /* effective_dir = workdir/name — must match load_primary_config() path */ + /* effective_dir = workdir/name — must match load_primary_config() path. + * Width-limited %.*s: workdir/name fit effective_dir; the fixed suffixes + * appended below (≤32 bytes) then provably fit conf_dir-derived paths. */ char effective_dir[4096]; - snprintf(effective_dir, sizeof(effective_dir), "%s/%s", - myconf->workdir, myconf->name); + snprintf(effective_dir, sizeof(effective_dir), "%.*s/%.*s", + (int)(sizeof(effective_dir) / 2), myconf->workdir, + (int)(sizeof(effective_dir) / 2 - 2), myconf->name); char conf_dir[4096]; make_conf_dir(effective_dir, conf_dir, sizeof(conf_dir)); @@ -838,10 +853,13 @@ int conf_save_config(myconf_t *myconf, const uint8_t *bytes, size_t len, /* Step 1: write versioned file via thread-unique .tmp */ char tmp_path[4096], ver_path[4096]; - snprintf(tmp_path, sizeof(tmp_path), "%s/cluster.bin.%s.%lu.tmp", - conf_dir, hex_tag, (unsigned long)pthread_self()); - snprintf(ver_path, sizeof(ver_path), "%s/cluster.bin.%s", - conf_dir, hex_tag); + snprintf(tmp_path, sizeof(tmp_path), "%.*s/cluster.bin.%s.%lu.tmp", + (int)(sizeof(tmp_path) - sizeof("/cluster.bin.") - 12 + - sizeof(".18446744073709551615.tmp")), conf_dir, + hex_tag, (unsigned long)pthread_self()); + snprintf(ver_path, sizeof(ver_path), "%.*s/cluster.bin.%s", + (int)(sizeof(ver_path) - sizeof("/cluster.bin.") - 12), conf_dir, + hex_tag); int fd = open(tmp_path, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) @@ -864,9 +882,12 @@ int conf_save_config(myconf_t *myconf, const uint8_t *bytes, size_t len, /* Step 2: update HEAD pointer via thread-unique .tmp */ char ptr_tmp[4096], ptr_path[4096]; - snprintf(ptr_tmp, sizeof(ptr_tmp), "%s/current.%lu.tmp", - conf_dir, (unsigned long)pthread_self()); - snprintf(ptr_path, sizeof(ptr_path), "%s/current", conf_dir); + snprintf(ptr_tmp, sizeof(ptr_tmp), "%.*s/current.%lu.tmp", + (int)(sizeof(ptr_tmp) - sizeof("/current.") + - sizeof(".18446744073709551615.tmp")), conf_dir, + (unsigned long)pthread_self()); + snprintf(ptr_path, sizeof(ptr_path), "%.*s/current", + (int)(sizeof(ptr_path) - sizeof("/current")), conf_dir); char target[NAME_MAX]; snprintf(target, sizeof(target), "cluster.bin.%s\n", hex_tag); @@ -975,7 +996,9 @@ uint64_t conf_get_saved_tag(const char *workdir) return 0; char ver_path[4096]; - snprintf(ver_path, sizeof(ver_path), "%s/conf/%s", workdir, fname); + snprintf(ver_path, sizeof(ver_path), "%.*s/conf/%.*s", + (int)(sizeof(ver_path) - sizeof("/conf/") - 256), workdir, + 256, fname); uint8_t *bytes = NULL; size_t blen = 0; @@ -1003,7 +1026,9 @@ int conf_check_stale(const char *workdir, time_t stale_timeout_s) return 0; char ver_path[4096]; - snprintf(ver_path, sizeof(ver_path), "%s/conf/%s", workdir, fname); + snprintf(ver_path, sizeof(ver_path), "%.*s/conf/%.*s", + (int)(sizeof(ver_path) - sizeof("/conf/") - 256), workdir, + 256, fname); struct stat st; if (stat(ver_path, &st) != 0) @@ -1062,12 +1087,14 @@ void conf_trim_old_versions(const char *workdir, int keep_n) continue; if (strstr(e->d_name, ".tmp") != NULL) { char full[4096]; - snprintf(full, sizeof(full), "%s/%s", conf_dir, e->d_name); + snprintf(full, sizeof(full), "%.*s/%s", + (int)(sizeof(full) - 1 - 256), conf_dir, e->d_name); unlink(full); continue; } char full[4096]; - snprintf(full, sizeof(full), "%s/%s", conf_dir, e->d_name); + snprintf(full, sizeof(full), "%.*s/%s", + (int)(sizeof(full) - 1 - 256), conf_dir, e->d_name); struct stat st; if (stat(full, &st) == 0) { strncpy(entries[n].name, e->d_name, NAME_MAX - 1); @@ -1086,7 +1113,8 @@ void conf_trim_old_versions(const char *workdir, int keep_n) if (strcmp(entries[i].name, current_name) == 0) continue; char full[4096]; - snprintf(full, sizeof(full), "%s/%s", conf_dir, entries[i].name); + snprintf(full, sizeof(full), "%.*s/%s", + (int)(sizeof(full) - 1 - 256), conf_dir, entries[i].name); unlink(full); } } @@ -1121,7 +1149,10 @@ int load_primary_config_for_test(cluster_t *c) { myconf_t *myconf = c->myconf; char conf_dir[4096]; - snprintf(conf_dir, sizeof(conf_dir), "%s/%s", myconf->workdir, myconf->name); + /* Width-limited: same budget split as load_primary_config() */ + snprintf(conf_dir, sizeof(conf_dir), "%.*s/%.*s", + (int)(sizeof(conf_dir) / 2), myconf->workdir, + (int)(sizeof(conf_dir) / 2 - 2), myconf->name); char fname[256] = {0}; int rc = conf_read_current_filename(conf_dir, fname, sizeof(fname)); @@ -2549,8 +2580,11 @@ int ha_stream_wal_to_standby(endpoint_t *ep, const char *wal_path, break; char seg_path[4096]; + /* %.*s bounds wal_path so "seg-<16 hex>.wal" (26 bytes) always fits */ snprintf(seg_path, sizeof(seg_path), - "%s/seg-%016" PRIx64 ".wal", wal_path, seg_lsns[si]); + "%.*s/seg-%016" PRIx64 ".wal", + (int)(sizeof(seg_path) - sizeof("/seg-0000000000000000.wal")), + wal_path, seg_lsns[si]); int fd = open(seg_path, O_RDONLY); if (fd < 0) continue; @@ -3136,8 +3170,11 @@ int ha_send_snapshot_to_standby(endpoint_t *ep, const char *snap_dir, return -EINVAL; char snap_path[4096]; + /* %.*s bounds snap_dir so "snap-<16 hex>.capnp" (27 bytes) always fits */ snprintf(snap_path, sizeof(snap_path), - "%s/snap-%016" PRIx64 ".capnp", snap_dir, checkpoint_lsn); + "%.*s/snap-%016" PRIx64 ".capnp", + (int)(sizeof(snap_path) - sizeof("/snap-0000000000000000.capnp")), + snap_dir, checkpoint_lsn); /* Stat the snapshot file to get total_size */ struct stat st; diff --git a/src/controller/ha.c b/src/controller/ha.c index 6c382434..85902351 100644 --- a/src/controller/ha.c +++ b/src/controller/ha.c @@ -164,9 +164,13 @@ static int upgrade_materialization_read_live_config_sha256(cluster_t *c, return -ENOENT; /* effective_dir = workdir/name — must match conf_save_config's own path - * construction (config_repl.c) exactly, mirroring local_config_sha256. */ + * construction (config_repl.c) exactly, mirroring local_config_sha256. + * Width-limited %.*s: workdir/name fit conf_dir so "/conf/" (fixed + * + 256-byte tail) provably fits path (4096+256) below. */ char conf_dir[4096]; - snprintf(conf_dir, sizeof(conf_dir), "%s/%s", mc->workdir, mc->name); + snprintf(conf_dir, sizeof(conf_dir), "%.*s/%.*s", + (int)(sizeof(conf_dir) / 2), mc->workdir, + (int)(sizeof(conf_dir) / 2 - 2), mc->name); char fname[256] = {0}; int rc = conf_read_current_filename(conf_dir, fname, sizeof(fname)); @@ -174,7 +178,9 @@ static int upgrade_materialization_read_live_config_sha256(cluster_t *c, return -ENOENT; /* no local bytes yet — caller fences + retries */ char path[4352]; - snprintf(path, sizeof(path), "%s/conf/%s", conf_dir, fname); + snprintf(path, sizeof(path), "%.*s/conf/%.*s", + (int)(sizeof(path) - sizeof("/conf/") - 256), conf_dir, 256, + fname); uint8_t *bytes = NULL; size_t blen = 0; diff --git a/src/controller/main.c b/src/controller/main.c index b3741d91..2c1a476a 100644 --- a/src/controller/main.c +++ b/src/controller/main.c @@ -421,11 +421,16 @@ int main(int argc, char* argv[]) char certdir_buf[XCE_MAXPATH_LEN + 1]; if (!certdir) { snprintf(certdir_buf, sizeof(certdir_buf), - "%s/certs", arguments.workdir); + "%.*s/certs", + (int)(sizeof(certdir_buf) - sizeof("/certs")), + arguments.workdir); certdir = certdir_buf; } - snprintf(key_file, XCE_MAXPATH_LEN, "%s/xce.key", certdir); - snprintf(cert_file, XCE_MAXPATH_LEN, "%s/xce.crt", certdir); + /* %.*s bounds certdir so the fixed "/xce.key" / "/xce.crt" tails fit */ + snprintf(key_file, XCE_MAXPATH_LEN, "%.*s/xce.key", + (int)(XCE_MAXPATH_LEN - sizeof("/xce.key")), certdir); + snprintf(cert_file, XCE_MAXPATH_LEN, "%.*s/xce.crt", + (int)(XCE_MAXPATH_LEN - sizeof("/xce.crt")), certdir); myconf.cluster_config = NULL; myconf.conffile = NULL; /* set by load_primary_config() or fetch_config_from_primary() */ diff --git a/src/controller/meson.build b/src/controller/meson.build index cfaf4469..0be6fe6a 100644 --- a/src/controller/meson.build +++ b/src/controller/meson.build @@ -245,6 +245,18 @@ mkdtemp_clean_lib = static_library( dependencies: [unity_dep]) controller_unit_test_deps += declare_dependency(link_with: mkdtemp_clean_lib) +# -Wformat-truncation suppression, testsuite-wide (build/de-nix): the fixture +# files build scratch paths with snprintf(dir, 4096, "%s/") where dir +# is a mkdtemp() result -- gcc cannot prove the literal tail fits, but the +# fixtures never approach PATH_MAX (mkdtemp dirs are /tmp/xce_*, tens of +# bytes), so every one of these is a false positive. Hand-fixing each site +# would bury test intent in width-specifier noise; production sources keep the +# warning active (all 53 prod sites were hand-fixed with width-limited %.*s in +# build/de-nix). Attached to controller_unit_test_deps rather than per-target +# so every test executable sharing this deps list inherits it automatically. +controller_unit_test_deps += declare_dependency( + compile_args: ['-Wno-format-truncation']) + controller_unit_test = executable('controller_unit_test', controller_unit_test_src, include_directories: [incdir], diff --git a/src/controller/persist.c b/src/controller/persist.c index 578713b6..c4afef88 100644 --- a/src/controller/persist.c +++ b/src/controller/persist.c @@ -592,7 +592,12 @@ static int capnp_encode_queue_admin_state(const capnp_queue_admin_state_t* q, /* Constants */ /* ------------------------------------------------------------------ */ -#define WAL_SEG_FMT "%s/seg-%016" PRIx64 ".wal" +/* Segment paths are built with a width-limited %.*s so -Wformat-truncation + * can prove "seg-<16 hex>.wal" (26 bytes incl. '/') always fits seg_path[4096] + * even when wal_path is at its own 4096 max. */ +#define WAL_SEG_FMT "%.*s/seg-%016" PRIx64 ".wal" +#define WAL_SEG_WALPATH_MAX ((int)(sizeof(((persist_t*)0)->seg_path) \ + - sizeof("/seg-0000000000000000.wal"))) /* NFS_SUPER_MAGIC — reject WAL on NFS mounts (unreliable fsync) */ #define NFS_SUPER_MAGIC 0x6969 @@ -636,8 +641,12 @@ static int mkdir_p(const char* path, mode_t mode) /* Open (and pre-allocate) a new WAL segment named after current_lsn */ static int open_new_segment(persist_t* p) { + /* %.*s bounds wal_path so "seg-<16 hex>.wal" (26 bytes) always fits in + * seg_path even when wal_path itself is already at its 4096 max. */ snprintf(p->seg_path, sizeof(p->seg_path), - WAL_SEG_FMT, p->wal_path, p->current_lsn); + "%.*s/seg-%016" PRIx64 ".wal", + (int)(sizeof(p->seg_path) - sizeof("/seg-0000000000000000.wal")), + p->wal_path, p->current_lsn); int fd = open(p->seg_path, O_RDWR | O_CREAT | O_TRUNC, 0600); if (fd < 0) @@ -1158,10 +1167,17 @@ void persist_reconcile_checkpoint_term(persist_t* p, uint64_t checkpoint_lsn, void persist_set_workdir(persist_t* p, const char* workdir, const char* name) { + /* Width-limited %.*s makes every truncation below explicit and provable + * for -Wformat-truncation: workdir/name share the budget of `effective`, + * and `effective` leaves room for the "/data/..." suffixes downstream. */ char effective[4096]; - snprintf(effective, sizeof(effective), "%s/%s", workdir, name); - snprintf(p->wal_path, sizeof(p->wal_path), "%s/data/wal", effective); - snprintf(p->snap_path, sizeof(p->snap_path), "%s/data/snap", effective); + snprintf(effective, sizeof(effective), "%.*s/%.*s", + (int)(sizeof(effective) / 2), workdir, + (int)(sizeof(effective) / 2 - 2), name); + snprintf(p->wal_path, sizeof(p->wal_path), "%.*s/data/wal", + (int)(sizeof(p->wal_path) - sizeof("/data/wal")), effective); + snprintf(p->snap_path, sizeof(p->snap_path), "%.*s/data/snap", + (int)(sizeof(p->snap_path) - sizeof("/data/snap")), effective); } static int dmcrypt_walk(const char* sysfs, unsigned maj, unsigned min, @@ -1766,7 +1782,7 @@ static int read_entry_meta_locked(persist_t* p, uint64_t lsn, char seg_path[4096]; snprintf(seg_path, sizeof(seg_path), - WAL_SEG_FMT, p->wal_path, seg_lsns[si]); + WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[si]); int fd = open(seg_path, O_RDONLY); if (fd < 0) continue; @@ -2315,7 +2331,7 @@ uint64_t persist_test_durable_lsn_on_disk(persist_t* p) for (int si = 0; si < nseg; si++) { char seg_path[4096]; snprintf(seg_path, sizeof(seg_path), - WAL_SEG_FMT, p->wal_path, seg_lsns[si]); + WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[si]); int fd = open(seg_path, O_RDONLY); if (fd < 0) @@ -2985,10 +3001,16 @@ static int write_snapshot(persist_t* p) char tmp_path[4096]; char final_path[4096]; + /* %.*s bounds snap_path so the fixed "snap-<16 hex>." suffixes + * (26/27 bytes) always fit even at snap_path's 4096 max. */ snprintf(tmp_path, sizeof(tmp_path), - "%s/snap-%016" PRIx64 ".tmp", p->snap_path, p->checkpoint_lsn); + "%.*s/snap-%016" PRIx64 ".tmp", + (int)(sizeof(tmp_path) - sizeof("/snap-0000000000000000.tmp")), + p->snap_path, p->checkpoint_lsn); snprintf(final_path, sizeof(final_path), - "%s/snap-%016" PRIx64 ".capnp", p->snap_path, p->checkpoint_lsn); + "%.*s/snap-%016" PRIx64 ".capnp", + (int)(sizeof(final_path) - sizeof("/snap-0000000000000000.capnp")), + p->snap_path, p->checkpoint_lsn); /* Collect + encode entities BEFORE opening the tmp file: a collection * failure (Requirement 1.3) then never creates a tmp file at all. */ @@ -3221,7 +3243,7 @@ static void scan_latest_committed_config_ref(persist_t* p) for (int si = 0; si < nseg; si++) { char seg_path[4096]; - snprintf(seg_path, sizeof(seg_path), WAL_SEG_FMT, p->wal_path, + snprintf(seg_path, sizeof(seg_path), WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[si]); int fd = open(seg_path, O_RDONLY); if (fd < 0) @@ -3349,7 +3371,10 @@ static void trim_wal_segments(persist_t* p) * so this check subsumes the old < active_seg_lsn guard. */ if (seg_start_lsn < floor) { char seg_path[4096]; - snprintf(seg_path, sizeof(seg_path), "%s/%s", p->wal_path, e->d_name); + /* d_name is capped at 255 (NAME_MAX); %.*s bounds wal_path so the + * "/" tail always fits. */ + snprintf(seg_path, sizeof(seg_path), "%.*s/%s", + (int)(sizeof(seg_path) - 1 - 256), p->wal_path, e->d_name); unlink(seg_path); } } @@ -3422,7 +3447,10 @@ static void rotate_snapshots(persist_t* p) continue; char path[4096]; - snprintf(path, sizeof(path), "%s/%s", p->snap_path, names[i]); + /* names[] entries are dirent d_name (≤255); %.*s bounds snap_path so + * the "/" tail always fits. */ + snprintf(path, sizeof(path), "%.*s/%s", + (int)(sizeof(path) - 1 - 256), p->snap_path, names[i]); unlink(path); } @@ -5804,7 +5832,7 @@ static int apply_pump_read_entry(persist_t* p, uint64_t lsn, break; char seg_path[4096]; - snprintf(seg_path, sizeof(seg_path), WAL_SEG_FMT, p->wal_path, + snprintf(seg_path, sizeof(seg_path), WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[si]); int fd = open(seg_path, O_RDONLY); if (fd < 0) @@ -6299,7 +6327,7 @@ static int replay_wal(persist_t* p, uint64_t from_lsn, for (int si = 0; si < nseg; si++) { char seg_path[4096]; snprintf(seg_path, sizeof(seg_path), - WAL_SEG_FMT, p->wal_path, seg_lsns[si]); + WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[si]); int fd = open(seg_path, O_RDONLY); if (fd < 0) { @@ -6852,8 +6880,11 @@ int persist_recover(persist_t* p) continue; if (lsn > snap_lsn) { snap_lsn = lsn; + /* d_name ≤255; %.*s bounds snap_path so "/" always fits */ snprintf(snap_file, sizeof(snap_file), - "%s/%s", p->snap_path, e->d_name); + "%.*s/%s", + (int)(sizeof(snap_file) - 1 - 256), p->snap_path, + e->d_name); } } closedir(d); @@ -9021,7 +9052,7 @@ static int truncate_wal_above_locked(persist_t* p, uint64_t cutoff_lsn) for (int i = 0; i < nseg; i++) { char del_path[4096]; snprintf(del_path, sizeof(del_path), - WAL_SEG_FMT, p->wal_path, seg_lsns[i]); + WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[i]); unlink(del_path); } if (p->wal_fd >= 0) { @@ -9044,7 +9075,7 @@ static int truncate_wal_above_locked(persist_t* p, uint64_t cutoff_lsn) /* --- Scan segment to find byte offset of first entry with lsn > cutoff --- */ char cutoff_seg_path[4096]; snprintf(cutoff_seg_path, sizeof(cutoff_seg_path), - WAL_SEG_FMT, p->wal_path, seg_lsns[cutoff_seg_idx]); + WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[cutoff_seg_idx]); int scan_fd = open(cutoff_seg_path, O_RDONLY); if (scan_fd < 0) { @@ -9100,7 +9131,7 @@ static int truncate_wal_above_locked(persist_t* p, uint64_t cutoff_lsn) for (int i = cutoff_seg_idx + 1; i < nseg; i++) { char del_path[4096]; snprintf(del_path, sizeof(del_path), - WAL_SEG_FMT, p->wal_path, seg_lsns[i]); + WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[i]); unlink(del_path); } @@ -9108,7 +9139,7 @@ static int truncate_wal_above_locked(persist_t* p, uint64_t cutoff_lsn) p->wal_fd = new_fd; p->seg_offset = trunc_off; snprintf(p->seg_path, sizeof(p->seg_path), - WAL_SEG_FMT, p->wal_path, seg_lsns[cutoff_seg_idx]); + WAL_SEG_FMT, WAL_SEG_WALPATH_MAX, p->wal_path, seg_lsns[cutoff_seg_idx]); p->current_lsn = cutoff_lsn + 1; p->last_crc = new_last_crc; atomic_store_explicit(&p->committed_lsn, cutoff_lsn, memory_order_release); diff --git a/src/scheduler/testsuite/meson.build b/src/scheduler/testsuite/meson.build index 5b32c892..cb4f1c6e 100644 --- a/src/scheduler/testsuite/meson.build +++ b/src/scheduler/testsuite/meson.build @@ -26,6 +26,18 @@ mkdtemp_clean_lib = static_library( join_paths(meson.source_root(), 'testsuite_support', 'mkdtemp_clean.c')) scheduler_test_deps += declare_dependency(link_with: mkdtemp_clean_lib) +# -Wformat-truncation suppression, testsuite-wide (build/de-nix): the white-box +# fixtures build scratch paths with snprintf(dir, 4096, "%s/") where +# dir is a mkdtemp() result -- gcc cannot prove the literal tail fits, but the +# fixtures never approach PATH_MAX (mkdtemp dirs are /tmp/xce_*, tens of +# bytes), so every one of these is a false positive. Hand-fixing each site +# would bury test intent in width-specifier noise; production sources keep the +# warning active (all 53 prod sites were hand-fixed with width-limited %.*s in +# build/de-nix). Applied here rather than per-executable so every current and +# future target sharing scheduler_test_deps inherits it automatically. +scheduler_test_deps += declare_dependency( + compile_args: ['-Wno-format-truncation']) + # and both resolve through unity_dep itself: the # wrap-path override (or the nix pc under the legacy build) carries the # include roots for both layouts (same change as src/lib/meson.build). diff --git a/src/subprojects/c-capnproto/meson.build b/src/subprojects/c-capnproto/meson.build index e6d7ed5f..20ec04fe 100644 --- a/src/subprojects/c-capnproto/meson.build +++ b/src/subprojects/c-capnproto/meson.build @@ -3,7 +3,19 @@ project('capnp-c', ['c','cpp'], meson_version: '>=1.0.0', default_options : ['c_ pkg = import('pkgconfig') cc = meson.get_compiler('c') -common_c_args = [] +# -Wno-switch (build/de-nix): capnpc-c.c's per-node-type dispatch is an +# exhaustive switch over the vendored schema-union tags; gcc's -Wswitch fires +# on it ~40 times (one per enumerator handled in other arms). +# -Wno-unused-function: the empty define_encode_function() stub (upstream left +# it defined-but-uncalled). +# -Wno-format-overflow: sprintf(uniontagvar, "d->%s", buf) at capnpc-c.c:2054 +# -- 255-byte uniontag + 3-byte prefix vs the 256-byte buffer; a theoretical +# schema-name-length overflow in the codegen tool, not reachable from any +# schema we feed it. +# All vendored third-party code -- not ours to restructure, and none of our +# code links or includes it. +common_c_args = ['-Wno-switch', '-Wno-unused-function', + '-Wno-format-overflow'] common_cpp_args = ['-std=c++14'] libcapnp_c_args = [] libcapnp_src = [ diff --git a/src/subprojects/packagefiles/c-capnproto/meson.build b/src/subprojects/packagefiles/c-capnproto/meson.build index e6d7ed5f..20ec04fe 100644 --- a/src/subprojects/packagefiles/c-capnproto/meson.build +++ b/src/subprojects/packagefiles/c-capnproto/meson.build @@ -3,7 +3,19 @@ project('capnp-c', ['c','cpp'], meson_version: '>=1.0.0', default_options : ['c_ pkg = import('pkgconfig') cc = meson.get_compiler('c') -common_c_args = [] +# -Wno-switch (build/de-nix): capnpc-c.c's per-node-type dispatch is an +# exhaustive switch over the vendored schema-union tags; gcc's -Wswitch fires +# on it ~40 times (one per enumerator handled in other arms). +# -Wno-unused-function: the empty define_encode_function() stub (upstream left +# it defined-but-uncalled). +# -Wno-format-overflow: sprintf(uniontagvar, "d->%s", buf) at capnpc-c.c:2054 +# -- 255-byte uniontag + 3-byte prefix vs the 256-byte buffer; a theoretical +# schema-name-length overflow in the codegen tool, not reachable from any +# schema we feed it. +# All vendored third-party code -- not ours to restructure, and none of our +# code links or includes it. +common_c_args = ['-Wno-switch', '-Wno-unused-function', + '-Wno-format-overflow'] common_cpp_args = ['-std=c++14'] libcapnp_c_args = [] libcapnp_src = [ diff --git a/src/worker/testsuite/test_worker_launch_type_dispatch.c b/src/worker/testsuite/test_worker_launch_type_dispatch.c index a78b2040..94393a90 100644 --- a/src/worker/testsuite/test_worker_launch_type_dispatch.c +++ b/src/worker/testsuite/test_worker_launch_type_dispatch.c @@ -759,5 +759,11 @@ int main(void) RUN_TEST(test_xcecd_job_remote_start_success_path); RUN_TEST(test_xcecd_job_remote_start_failure_path_reports_task_fail); + /* bug-924 /tmp/xce_* hygiene: the fixture is a fixed-path dir (not + * mkdtemp), so the mkdtemp_clean shim can't see it -- remove it here, + * after every test that could still want the fake launcher is done. */ + remove("/tmp/xce_test_worker_launch_type_dispatch_xrun/xrun"); + rmdir("/tmp/xce_test_worker_launch_type_dispatch_xrun"); + return UNITY_END(); }