Skip to content

Intermediate Gotchas

The Path That Ignored Its Directory

a POSIX-absolute filename that silently overrides the base

namespace fs = std::filesystem;

int main() {
  fs::path config_dir = "/srv/app";
  fs::path name = "/etc/app.conf";

  std::cout << (config_dir / name).string() << '\n';
}

Which directory appears in the resulting path?

Answer

On GCC 11.5/Linux:

/etc/app.conf

The POSIX-absolute right-hand path replaced /srv/app.

Why

std::filesystem::path operator/ follows native path-append rules, not string concatenation rules. On POSIX, /etc/app.conf is absolute, so it replaces the left-hand path instead of becoming a child of it. Windows distinguishes a root name from a root directory; a rooted path without a drive can preserve the left path's root name, so the exact native result can differ there. This GCC/Linux output is surprising when a path came from untrusted or unchecked configuration. GCC 11.5 emits no warning under -Wall -Wextra.

The fix

if (name.has_root_name() || name.has_root_directory())
  return 1;
const fs::path config = config_dir / name;

Takeaway: reject root components before appending an untrusted path to a trusted base.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry