Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

msys check fails with long paths #34

Closed
nikhilm opened this issue Jul 5, 2019 · 6 comments
Closed

msys check fails with long paths #34

nikhilm opened this issue Jul 5, 2019 · 6 comments

Comments

@nikhilm
Copy link

nikhilm commented Jul 5, 2019

atty/src/lib.rs

Line 118 in c92ca03

let mut name_info_bytes = vec![0u8; size + MAX_PATH * mem::size_of::<WCHAR>()];

Windows 10 supports longer paths than MAXPATH. When stdout is attached to such a file, the above code panics because it tries to index beyond MAXPATH + 8.

I think this code should be modified to allocate up to 32,767 plus some buffer (see the Note at https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file).

@BurntSushi
Copy link
Contributor

Can you show a backtrace? I can't see where the panic originates.

@nikhilm
Copy link
Author

nikhilm commented Jul 5, 2019

My apologies. I'm not sure any more if this will apply to the atty crate. I'm using the deprecated isatty crate instead (code is part of a larger code base, so I can't change this) and I didn't realize that is a truly different crate that is not deprecated (and I assume this is the replacement). The code is similar, but not exactly the same, as this crate does not access the slice, but does raw pointer access. That said, it seems the from_raw_parts may UB due to reading past the end of the MAX_PATH allocated name_info_bytes buffer if the FileNameLength is longer?

Here is the backtrace from the isatty impl.

thread 'conversion::tests::derive' panicked at 'index 272 out of range for slice of length 268', src\libcore\slice\mod.rs:2569:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys_common::backtrace::print
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\/src\libstd\sys_common\backtrace.rs:59
   1: std::panicking::default_hook::{{closure}}
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\/src\libstd\panicking.rs:197
   2: std::panicking::default_hook
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\/src\libstd\panicking.rs:208
   3: std::panicking::rust_panic_with_hook
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\/src\libstd\panicking.rs:474
   4: std::panicking::continue_panic_fmt
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\/src\libstd\panicking.rs:381
   5: std::panicking::rust_begin_panic
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\/src\libstd\panicking.rs:308
   6: core::panicking::panic_fmt
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\/src\libcore\panicking.rs:85
   7: core::slice::slice_index_len_fail
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\/src\libcore\slice\mod.rs:2569
   8: core::slice::{{impl}}::index
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\src\libcore\slice\mod.rs:2746
   9: core::slice::{{impl}}::index
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\src\libcore\slice\mod.rs:2552
  10: alloc::vec::{{impl}}::index
             at /rustc/50a0defd5a93523067ef239936cc2e0755220904\src\liballoc\vec.rs:1687
  11: isatty::is_cygwin_pty
             at /rust_vendor/isatty-0.1.9/src/lib.rs:138
  12: isatty::isatty
             at /rust_vendor/isatty-0.1.9/src/lib.rs:111
  13: slog_term::AnyTerminal::should_use_color
             at /rust_vendor/slog-term-2.4.0/src/lib.rs:1176
  14: slog_term::TermDecoratorBuilder::build
             at /rust_vendor/slog-term-2.4.0/src/lib.rs:1259

The slog-term bug is slog-rs/slog#214
268 is 8 + MAXPATH.

Feel free to close if you don't consider this applicable.

@BurntSushi
Copy link
Contributor

That said, it seems the from_raw_parts may UB due to reading past the end of the MAX_PATH allocated name_info_bytes buffer if the FileNameLength is longer?

Yeah, that's exactly what I was thinking, in that it would be UB and not a panic, which is worse. I'd consider this a bug in this crate, definitely.

@nikhilm
Copy link
Author

nikhilm commented Jul 5, 2019

I think atty is safe because it handles wchars properly, whereas isatty assumes chars.

When atty hits the windows call, it has allocated a struct of size 8 + 2*260 = 528 bytes, whereas isatty has allocated 268.

When GetFileInformationByHandleEx encounters a path > what would fit in the buffer, it returns error 234 (more data available) and we hit the early return.

when the path is exactly 262 wchars (524 bytes):
atty: correctly reads from byte 4 (FileName offset) to FileNameLength / 2 (*2 since from_raw_parts operates on T, not bytes) -> till 528, which is fine.

for isatty, the same early return happens at 133 wchars and onwards
when the path is 131 wchars (262 bytes):
isatty attempts to index the slice from (incorrect) index 8 to index (262 + 8) which panics.
It similarly fails for 132.

Ref:
https://github.com/dtolnay/isatty/blob/1994ab57dabc3ee943e4a87df252bf02075d1bdc/src/lib.rs#L138

I'm going to consider this closed, as slog-term needs to use this crate.

@nikhilm nikhilm closed this as completed Jul 5, 2019
@nikhilm
Copy link
Author

nikhilm commented Jul 5, 2019

if you want to play with this - https://gist.github.com/nikhilm/34d156f58ea353ed3275b434dcaf5808
I did have to comment out all the pre-msys checks in atty to reliably get that code path to execute

@BurntSushi
Copy link
Contributor

Ah okay, great, thanks for the analysis!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants