Simple fs::read_to_string(_) program causes valgrind memcheck errors

Issue : I wrote a proof of concept program which reads a file as string and prints it. but it causes multiple statx errors while testing it with valgrind memcheck.

Rustc version =>

rustc 1.57.0 (f1edd0429 2021-11-29)
binary: rustc
commit-hash: f1edd0429582dd29cccacaf50fd134b05593bd9c
commit-date: 2021-11-29
host: x86_64-unknown-linux-gnu
release: 1.57.0
LLVM version: 13.0.0

Here's the program I'm running and testing with valgrind =>

use std::fs;

fn main() {
    let content = fs::read_to_string("/home/palash/fuu/a.txt").unwrap();
    println!("{}" , content);
}

If I build the program with/without --release and try to test with valgrind memcheck, it shows multiple statx errors.

Valgrind Error
==35534== Memcheck, a memory error detector
==35534== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==35534== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==35534== Command: ./target/debug/fuu
==35534== Parent PID: 32919
==35534== 
==35534== Syscall param statx(file_name) points to unaddressable byte(s)
==35534==    at 0x4B179FE: statx (statx.c:29)
==35534==    by 0x12B490: statx (weak.rs:136)
==35534==    by 0x12B490: std::sys::unix::fs::try_statx (fs.rs:139)
==35534==    by 0x122645: file_attr (fs.rs:776)
==35534==    by 0x122645: metadata (fs.rs:493)
==35534==    by 0x122645: buffer_capacity_required (fs.rs:609)
==35534==    by 0x122645: <std::fs::File as std::io::Read>::read_to_string (fs.rs:645)
==35534==    by 0x122586: std::fs::read_to_string::inner (fs.rs:271)
==35534==    by 0x110AF5: std::fs::read_to_string (fs.rs:274)
==35534==    by 0x11140C: fuu::main (main.rs:4)
==35534==    by 0x11104A: core::ops::function::FnOnce::call_once (function.rs:227)
==35534==    by 0x1115ED: std::sys_common::backtrace::__rust_begin_short_backtrace (backtrace.rs:123)
==35534==    by 0x1118D0: std::rt::lang_start::{{closure}} (rt.rs:146)
==35534==    by 0x126EEA: call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (function.rs:259)
==35534==    by 0x126EEA: do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panicking.rs:403)
==35534==    by 0x126EEA: try<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (panicking.rs:367)
==35534==    by 0x126EEA: catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panic.rs:133)
==35534==    by 0x126EEA: {closure#2} (rt.rs:128)
==35534==    by 0x126EEA: do_call<std::rt::lang_start_internal::{closure#2}, isize> (panicking.rs:403)
==35534==    by 0x126EEA: try<isize, std::rt::lang_start_internal::{closure#2}> (panicking.rs:367)
==35534==    by 0x126EEA: catch_unwind<std::rt::lang_start_internal::{closure#2}, isize> (panic.rs:133)
==35534==    by 0x126EEA: std::rt::lang_start_internal (rt.rs:128)
==35534==    by 0x11189F: std::rt::lang_start (rt.rs:145)
==35534==    by 0x11150B: main (in /home/palash/fuu/target/debug/fuu)
==35534==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==35534== 
==35534== Syscall param statx(buf) points to unaddressable byte(s)
==35534==    at 0x4B179FE: statx (statx.c:29)
==35534==    by 0x12B490: statx (weak.rs:136)
==35534==    by 0x12B490: std::sys::unix::fs::try_statx (fs.rs:139)
==35534==    by 0x122645: file_attr (fs.rs:776)
==35534==    by 0x122645: metadata (fs.rs:493)
==35534==    by 0x122645: buffer_capacity_required (fs.rs:609)
==35534==    by 0x122645: <std::fs::File as std::io::Read>::read_to_string (fs.rs:645)
==35534==    by 0x122586: std::fs::read_to_string::inner (fs.rs:271)
==35534==    by 0x110AF5: std::fs::read_to_string (fs.rs:274)
==35534==    by 0x11140C: fuu::main (main.rs:4)
==35534==    by 0x11104A: core::ops::function::FnOnce::call_once (function.rs:227)
==35534==    by 0x1115ED: std::sys_common::backtrace::__rust_begin_short_backtrace (backtrace.rs:123)
==35534==    by 0x1118D0: std::rt::lang_start::{{closure}} (rt.rs:146)
==35534==    by 0x126EEA: call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (function.rs:259)
==35534==    by 0x126EEA: do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panicking.rs:403)
==35534==    by 0x126EEA: try<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> (panicking.rs:367)
==35534==    by 0x126EEA: catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> (panic.rs:133)
==35534==    by 0x126EEA: {closure#2} (rt.rs:128)
==35534==    by 0x126EEA: do_call<std::rt::lang_start_internal::{closure#2}, isize> (panicking.rs:403)
==35534==    by 0x126EEA: try<isize, std::rt::lang_start_internal::{closure#2}> (panicking.rs:367)
==35534==    by 0x126EEA: catch_unwind<std::rt::lang_start_internal::{closure#2}, isize> (panic.rs:133)
==35534==    by 0x126EEA: std::rt::lang_start_internal (rt.rs:128)
==35534==    by 0x11189F: std::rt::lang_start (rt.rs:145)
==35534==    by 0x11150B: main (in /home/palash/fuu/target/debug/fuu)
==35534==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==35534== 
==35534== 
==35534== HEAP SUMMARY:
==35534==     in use at exit: 0 bytes in 0 blocks
==35534==   total heap usage: 12 allocs, 12 frees, 3,060 bytes allocated
==35534== 
==35534== All heap blocks were freed -- no leaks are possible
==35534== 
==35534== For lists of detected and suppressed errors, rerun with: -s
==35534== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

I looked up for similar issues on the official repo of rust and I found this issue #68979.
Is this a rust bug or am I doing something wrong?

FYI, I also tried compiling aforementioned program with rust nightly (rustc 1.59.0-nightly) but still same issue.

Any help will be appreciated.. Thank You

You are doing nothing wrong. From the issue it looks like it's an intentional workaround for a bug in Docker.

Does it compromise any security? Or should it be ignored?

Security? In what sense? It just causes a syscall to return an error. It looks like the syscall already expects null to be passed, so it should be fine. It's not pretty, but I don't see any obvious/common way to exploit a null pointer that is predictably checked and causes an error to be returned, rather than invoking UB.

Well, that's relieving :relieved:

For Anyone who encounters the same issue ->

This special case has been taken care by valgrind itself.
I built valgrind from source (from git repo), version 3.19.0.GIT and ran it; as expected, aforementioned error messages was no longer trashing my terminal.

You can find guide on how to build and install valgrind from source here -> https://valgrind.org/downloads/repository.html

2 Likes

Thanks, i am having the same issue, now i know i can wait for valgrind 3.19 and see if that fixes it!

If you use arch or any derivatives you will get the latest "fixed" version by default. While ubuntu is stuck with the older version.

Btw, you don't need to wait, you can just build it yourself from source. It just takes 1-2 minutes max to build and install.

1 Like

I'm running into this in a CI job on github, and yes it's based on ubuntu..

i'll look into using arch there.. thanks!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.