clash-verge-rev/clash-verge-rev · error · anyhow::Error

effective-user home lookup exceeded the maximum buffer size

Error message

effective-user home lookup exceeded the maximum buffer size

What it means

current_user_home() calls getpwuid_r in a loop, doubling the buffer on each ERANGE return until it exceeds 1 MiB (MAX_BUFFER_SIZE). Bailing past that ceiling stops an unbounded loop: an effective UID whose passwd lookup refuses to fit in a megabyte is treated as broken rather than allowed to grow forever.

Source

Thrown at src-tauri/src/utils/macos_launch_guard.rs:114

    std::fs::canonicalize(path).ok()
}

fn current_user_home() -> anyhow::Result<PathBuf> {
    const DEFAULT_BUFFER_SIZE: usize = 16 * 1024;
    const MAX_BUFFER_SIZE: usize = 1024 * 1024;

    let uid = unsafe { libc::geteuid() };
    let configured_size = unsafe { libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) };
    let mut buffer_size = if configured_size > 0 {
        usize::try_from(configured_size).unwrap_or(DEFAULT_BUFFER_SIZE)
    } else {
        DEFAULT_BUFFER_SIZE
    }
    .max(1024);

    loop {
        if buffer_size > MAX_BUFFER_SIZE {
            anyhow::bail!("effective-user home lookup exceeded the maximum buffer size");
        }

        let mut passwd = std::mem::MaybeUninit::<libc::passwd>::zeroed();
        let mut result = std::ptr::null_mut();
        let mut buffer = vec![0_u8; buffer_size];
        let code = unsafe {
            libc::getpwuid_r(
                uid,
                passwd.as_mut_ptr(),
                buffer.as_mut_ptr().cast(),
                buffer.len(),
                &mut result,
            )
        };
        if code == libc::ERANGE {
            buffer_size = buffer_size.saturating_mul(2);
            continue;
        }

View on GitHub (pinned to 5cad0f2799)

Solutions

  1. Run `dscacheutil -q user -a uid <uid>` and `id -p` to inspect what Directory Services returns for the user.
  2. Flush the directory cache: `dscacheutil -flushcache` then `killall -HUP mDNSResponder`.
  3. If the Mac is AD-bound, unbind/rebind or fix LDAP reachability to the domain controller.
  4. As a workaround, set the HOME environment variable and (if patched) the code falls back to it before giving up.

Example fix

// before
if buffer_size > MAX_BUFFER_SIZE {
    anyhow::bail!("effective-user home lookup exceeded the maximum buffer size");
}
// after - fall back to $HOME before giving up
if buffer_size > MAX_BUFFER_SIZE {
    if let Some(home) = std::env::var_os("HOME") {
        return Ok(PathBuf::from(home));
    }
    anyhow::bail!("effective-user home lookup exceeded the maximum buffer size");
}
Defensive patterns

Strategy: fallback

Validate before calling

fn safe_home() -> anyhow::Result<PathBuf> {
    match current_user_home() {
        Ok(p) => Ok(p),
        Err(_) => std::env::var_os("HOME").map(PathBuf::from)
            .ok_or_else(|| anyhow::anyhow!("no home directory resolvable")),
    }
}

Try / catch

let home = match current_user_home() {
    Ok(h) => h,
    Err(e) => match std::env::var_os("HOME") {
        Some(h) if !h.is_empty() => PathBuf::from(h),
        _ => return Err(e),
    },
};

Prevention

When it happens

Trigger: A misconfigured Directory Service (Open Directory, the AD plugin, or LDAP) returning getpwuid_r=ERANGE indefinitely; libc on a stripped-down macOS sandbox where sysconf(_SC_GETPW_R_SIZE_MAX) reports a wrong size; a corrupted passwd entry with pathological content.

Common situations: macOS bound to a broken AD; containerized/hardened macOS where directory services are restricted; a custom MDM profile that interferes with Open Directory; CI running the launch guard under a synthetic UID.

Related errors


AI-assisted analysis of clash-verge-rev/clash-verge-rev@5cad0f2799 (2026-08-12). Data as JSON: /api/errors/ebb93833c514e4f1. Report an issue: GitHub.