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

fs: Don't dereference a pointer to a too-small allocation #94272

Merged
merged 1 commit into from
Mar 7, 2022

Conversation

tavianator
Copy link
Contributor

ptr::addr_of!((*ptr).field) still requires ptr to point to an
appropriate allocation for its type. Since the pointer returned by
readdir() can be smaller than sizeof(struct dirent), we need to entirely
avoid dereferencing it as that type.

Link: rust-lang/miri#1981 (comment)
Link: #93459 (comment)

@rust-highfive
Copy link
Collaborator

r? @joshtriplett

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 23, 2022
@RalfJung
Copy link
Member

Since the pointer returned by
readdir() can be smaller than sizeof(struct dirent), we need to entirely
avoid dereferencing it as that type.

Alternatively, we could deref it at a different, sufficiently small type -- not sure if that is feasible here.

@tavianator
Copy link
Contributor Author

tavianator commented Feb 23, 2022

Alternatively, we could deref it at a different, sufficiently small type -- not sure if that is feasible here.

We could make a type that matches the layout of struct dirent except for the trailing array. But the fields vary between platforms, and it would be difficult to keep in sync. I'd rather just do this and rely on libc as the source of truth for the layout.

@tavianator
Copy link
Contributor Author

r? @cuviper

ptr::addr_of!((*ptr).field) still requires ptr to point to an
appropriate allocation for its type.  Since the pointer returned by
readdir() can be smaller than sizeof(struct dirent), we need to entirely
avoid dereferencing it as that type.

Link: rust-lang/miri#1981 (comment)
Link: rust-lang#93459 (comment)
@tavianator tavianator force-pushed the readdir-reclen-for-real branch from 684e0ce to 478cf8b Compare February 23, 2022 14:51
@RalfJung
Copy link
Member

RalfJung commented Mar 5, 2022

@cuviper friendly reminder that this is blocking getting readdir to work again in Miri. :)

@cuviper
Copy link
Member

cuviper commented Mar 6, 2022

Sorry, yeah, looks good.

@bors r+

@bors
Copy link
Contributor

bors commented Mar 6, 2022

📌 Commit 478cf8b has been approved by cuviper

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 6, 2022
@bors
Copy link
Contributor

bors commented Mar 7, 2022

⌛ Testing commit 478cf8b with merge 75640d6d8cc7bc15889d9c911fb337c1fe44a55c...

@rust-log-analyzer
Copy link
Collaborator

The job x86_64-msvc-cargo failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)

failures:

---- test_reverse::prop_reverse_headers stdout ----
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-773]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-779]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-786]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["¢\u{10fffe}\u{e}F", "\u{1a}"], ["\u{b73e2}I赶&", "佣 "], ["1\u{2063}", ""], ["\u{dd65a}\u{9b}@+", "`\u{19}\u{180e}"], ["", "$"], ["®", "5y8"], ["\u{9a}\u{6}\u{f}\u{202f}", "&0"], ["c", "x"], ["⎋-", "Xn¦\u{1e}"], ["", ">퍢"], ["\u{86}", "-"], ["", ""], ["\u{5c513}9*\u{82}", "\"klE"], ["\u{e}\u{16}\u{604}V", "0;\u{85c8c}\u{fffe}"], ["\u{f3c2b}-|{", ""], ["\u{1b}\\", "锉\u{fff8};"], ["", "of➴}"], ["", "ⴟ/n𛄔"], ["-\u{6}:h", "\u{dba71}"], ["_dk", "\u{2069}\u{ec5a}&"], ["", "\u{1d}"], ["\n/", ""], ["?", "¨\u{89}"], ["", "\u{fff8}¨_"], ["", "a"], ["\u{6}", "/\\¡¨"], ["", "\u{100f4e}핋&"], ["", "J0ª\u{ffffe}"], ["\u{fff7}", "\r\u{faeb}~<"], ["\u{4a36e}\u{4d44f}\u{92}\u{9b}", ""], ["-\u{2002}<𨇻", "®"], ["", "\u{8b}x"], ["\u{3}\u{86}䗄", "G\u{5}\u{8d}"], ["", "\u{8}\u{1b}"], ["}O", "3\u{92}ZK"], [" \u{601}\u{e167}", "\u{2065}\u{b49a7}\u{fff2}1"], ["", "050\u{5}"], ["j", ""], ["6/", "[\u{10fffd}"], ["\u{7f}u", "5\nB"], [" \u{e001}", "내"], ["{cHT", "LF⁃%"], ["", "}"], ["1𥩯-", "\u{ecb}#"], ["鐰", "\u{85}z\u{97}"], ["<䢖※\u{96}", "\u{f0000}$慰\u{2064}"], ["h", ""], ["<", "Ꮚ¢1"], [">", "\u{fff5}"], ["", "\u{5a6be}\u{8}!"], ["4q,", ""], ["㵟s", ">G"], ["ª", ""], ["", ":/"], [" ", "\n_#"], ["ⶂ", "R¢"], ["\u{b7895} 0", "ᦤ\u{19}\u{8c}¢"], ["'q\u{88}", "\u{ed08d}\u{9d}"], ["⁋\u{a0}", "\u{100000}鏒a"], ["\u{1b}/\t=", "~"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`,
 right: `[["\u{feff}\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["¢\u{10fffe}\u{e}F", "\u{1a}"], ["\u{b73e2}I赶&", "佣 "], ["1\u{2063}", ""], ["\u{dd65a}\u{9b}@+", "`\u{19}\u{180e}"], ["", "$"], ["®", "5y8"], ["\u{9a}\u{6}\u{f}\u{202f}", "&0"], ["c", "x"], ["⎋-", "Xn¦\u{1e}"], ["", ">퍢"], ["\u{86}", "-"], ["", ""], ["\u{5c513}9*\u{82}", "\"klE"], ["\u{e}\u{16}\u{604}V", "0;\u{85c8c}\u{fffe}"], ["\u{f3c2b}-|{", ""], ["\u{1b}\\", "锉\u{fff8};"], ["", "of➴}"], ["", "ⴟ/n𛄔"], ["-\u{6}:h", "\u{dba71}"], ["_dk", "\u{2069}\u{ec5a}&"], ["", "\u{1d}"], ["\n/", ""], ["?", "¨\u{89}"], ["", "\u{fff8}¨_"], ["", "a"], ["\u{6}", "/\\¡¨"], ["", "\u{100f4e}핋&"], ["", "J0ª\u{ffffe}"], ["\u{fff7}", "\r\u{faeb}~<"], ["\u{4a36e}\u{4d44f}\u{92}\u{9b}", ""], ["-\u{2002}<𨇻", "®"], ["", "\u{8b}x"], ["\u{3}\u{86}䗄", "G\u{5}\u{8d}"], ["", "\u{8}\u{1b}"], ["}O", "3\u{92}ZK"], [" \u{601}\u{e167}", "\u{2065}\u{b49a7}\u{fff2}1"], ["", "050\u{5}"], ["j", ""], ["6/", "[\u{10fffd}"], ["\u{7f}u", "5\nB"], [" \u{e001}", "내"], ["{cHT", "LF⁃%"], ["", "}"], ["1𥩯-", "\u{ecb}#"], ["鐰", "\u{85}z\u{97}"], ["<䢖※\u{96}", "\u{f0000}$慰\u{2064}"], ["h", ""], ["<", "Ꮚ¢1"], [">", "\u{fff5}"], ["", "\u{5a6be}\u{8}!"], ["4q,", ""], ["㵟s", ">G"], ["ª", ""], ["", ":/"], [" ", "\n_#"], ["ⶂ", "R¢"], ["\u{b7895} 0", "ᦤ\u{19}\u{8c}¢"], ["'q\u{88}", "\u{ed08d}\u{9d}"], ["⁋\u{a0}", "\u{100000}鏒a"], ["\u{1b}/\t=", "~"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`', tests\test_reverse.rs:22:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-825]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-831]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-837]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["\u{3}\u{86}䗄", "G\u{5}\u{8d}"], ["", "\u{8}\u{1b}"], ["}O", "3\u{92}ZK"], [" \u{601}\u{e167}", "\u{2065}\u{b49a7}\u{fff2}1"], ["", "050\u{5}"], ["j", ""], ["6/", "[\u{10fffd}"], ["\u{7f}u", "5\nB"], [" \u{e001}", "내"], ["{cHT", "LF⁃%"], ["", "}"], ["1𥩯-", "\u{ecb}#"], ["鐰", "\u{85}z\u{97}"], ["<䢖※\u{96}", "\u{f0000}$慰\u{2064}"], ["h", ""], ["<", "Ꮚ¢1"], [">", "\u{fff5}"], ["", "\u{5a6be}\u{8}!"], ["4q,", ""], ["㵟s", ">G"], ["ª", ""], ["", ":/"], [" ", "\n_#"], ["ⶂ", "R¢"], ["\u{b7895} 0", "ᦤ\u{19}\u{8c}¢"], ["'q\u{88}", "\u{ed08d}\u{9d}"], ["⁋\u{a0}", "\u{100000}鏒a"], ["\u{1b}/\t=", "~"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`,
 right: `[["\u{feff}\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["\u{3}\u{86}䗄", "G\u{5}\u{8d}"], ["", "\u{8}\u{1b}"], ["}O", "3\u{92}ZK"], [" \u{601}\u{e167}", "\u{2065}\u{b49a7}\u{fff2}1"], ["", "050\u{5}"], ["j", ""], ["6/", "[\u{10fffd}"], ["\u{7f}u", "5\nB"], [" \u{e001}", "내"], ["{cHT", "LF⁃%"], ["", "}"], ["1𥩯-", "\u{ecb}#"], ["鐰", "\u{85}z\u{97}"], ["<䢖※\u{96}", "\u{f0000}$慰\u{2064}"], ["h", ""], ["<", "Ꮚ¢1"], [">", "\u{fff5}"], ["", "\u{5a6be}\u{8}!"], ["4q,", ""], ["㵟s", ">G"], ["ª", ""], ["", ":/"], [" ", "\n_#"], ["ⶂ", "R¢"], ["\u{b7895} 0", "ᦤ\u{19}\u{8c}¢"], ["'q\u{88}", "\u{ed08d}\u{9d}"], ["⁋\u{a0}", "\u{100000}鏒a"], ["\u{1b}/\t=", "~"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-851]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-856]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-863]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], [">", "\u{fff5}"], ["", "\u{5a6be}\u{8}!"], ["4q,", ""], ["㵟s", ">G"], ["ª", ""], ["", ":/"], [" ", "\n_#"], ["ⶂ", "R¢"], ["\u{b7895} 0", "ᦤ\u{19}\u{8c}¢"], ["'q\u{88}", "\u{ed08d}\u{9d}"], ["⁋\u{a0}", "\u{100000}鏒a"], ["\u{1b}/\t=", "~"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`,
 right: `[["\u{feff}\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], [">", "\u{fff5}"], ["", "\u{5a6be}\u{8}!"], ["4q,", ""], ["㵟s", ">G"], ["ª", ""], ["", ":/"], [" ", "\n_#"], ["ⶂ", "R¢"], ["\u{b7895} 0", "ᦤ\u{19}\u{8c}¢"], ["'q\u{88}", "\u{ed08d}\u{9d}"], ["⁋\u{a0}", "\u{100000}鏒a"], ["\u{1b}/\t=", "~"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-870]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-876]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-882]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["\u{b7895} 0", "ᦤ\u{19}\u{8c}¢"], ["'q\u{88}", "\u{ed08d}\u{9d}"], ["⁋\u{a0}", "\u{100000}鏒a"], ["\u{1b}/\t=", "~"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`,
 right: `[["\u{feff}\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["\u{b7895} 0", "ᦤ\u{19}\u{8c}¢"], ["'q\u{88}", "\u{ed08d}\u{9d}"], ["⁋\u{a0}", "\u{100000}鏒a"], ["\u{1b}/\t=", "~"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-889]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-895]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-901]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`,
 right: `[["\u{feff}\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["\u{e}\u{96}(", "2"], ["", "(*O)"], ["8", "t"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-906]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-912]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-919]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["8", "t"]]`,
 right: `[["\u{feff}\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"], ["8", "t"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-924]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-930]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-936]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"]]`,
 right: `[["\u{feff}\u{fffff}K=", "\u{1};\u{100000}\u{2}"], ["x", "*/"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-943]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-949]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-955]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}K=", "\u{1};\u{100000}\u{2}"]]`,
 right: `[["\u{feff}\u{fffff}K=", "\u{1};\u{100000}\u{2}"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-960]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-966]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-973]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-977]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["\u{fffff}", "\u{1};\u{100000}\u{2}"]]`,
 right: `[["\u{feff}\u{fffff}", "\u{1};\u{100000}\u{2}"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-984]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-989]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-996]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1000]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["", "\u{1};\u{100000}\u{2}"]]`,
 right: `[["\u{feff}", "\u{1};\u{100000}\u{2}"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1007]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1011]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1015]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1023]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1028]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1034]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1039]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1046]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1050]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1058]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1063]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1068]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1074]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1080]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1084]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1090]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1094]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1099]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[["", ""]]`,
 right: `[["\u{feff}", ""]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1106]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1111]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1117]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1123]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1130]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1137]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1141]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1149]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1153]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1160]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1165]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1172]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1178]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1185]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1191]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1198]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1204]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1211]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1216]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1223]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at 'assertion failed: `(left == right)`
  left: `[]`,
 right: `[["\u{feff}"]]`', tests\test_reverse.rs:22:5
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1229]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1237]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1242]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1250]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1255]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1262]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1268]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1275]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1281]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1288]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1295]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1302]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1309]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1315]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1320]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1327]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
[D:\a\rust\rust\build\ct\xsv\target\debug\xit\prop_reverse_headers\test-1334]: "D:\\a\\rust\\rust\\build\\ct\\xsv\\target\\debug\\xsv" "reverse" "in.csv"
thread 'test_reverse::prop_reverse_headers' panicked at '[quickcheck] TEST FAILED (runtime error). Arguments: (CsvData { data: [[[239, 187, 191]]] })
Error: "assertion failed: `(left == right)`\n  left: `[]`,\n right: `[[\"\\u{feff}\"]]`"', C:\Users\runneradmin\.cargo\registry\src\github.com-1ecc6299db9ec823\quickcheck-0.7.1\src\tester.rs:176:28

failures:
    test_reverse::prop_reverse_headers

@bors
Copy link
Contributor

bors commented Mar 7, 2022

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Mar 7, 2022
@tavianator
Copy link
Contributor Author

I don't think the MSVC failure is related to this PR

@cuviper
Copy link
Member

cuviper commented Mar 7, 2022

@bors retry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 7, 2022
@bors
Copy link
Contributor

bors commented Mar 7, 2022

⌛ Testing commit 478cf8b with merge 2631aee...

@bors
Copy link
Contributor

bors commented Mar 7, 2022

☀️ Test successful - checks-actions
Approved by: cuviper
Pushing 2631aee to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Mar 7, 2022
@bors bors merged commit 2631aee into rust-lang:master Mar 7, 2022
@rustbot rustbot added this to the 1.61.0 milestone Mar 7, 2022
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (2631aee): comparison url.

Summary: This benchmark run did not return any relevant results.

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

@rustbot label: -perf-regression

@tavianator tavianator deleted the readdir-reclen-for-real branch March 7, 2022 13:26
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 23, 2022
Eliminate 280-byte memset from ReadDir iterator

This guy:

https://github.com/rust-lang/rust/blob/1536ab1b383f21b38f8d49230a2aecc51daffa3d/library/std/src/sys/unix/fs.rs#L589

It turns out `libc::dirent64` is quite big&mdash;https://docs.rs/libc/0.2.135/libc/struct.dirent64.html. In rust-lang#103135 this memset accounted for 0.9% of the runtime of iterating a big directory.

Almost none of the big zeroed value is ever used. We memcpy a tiny prefix (19 bytes) into it, and then read just 9 bytes (`d_ino` and `d_type`) back out. We can read exactly those 9 bytes we need directly from the original entry_ptr instead.

## History

This code got added in rust-lang#93459 and tweaked in rust-lang#94272 and rust-lang#94750.

Prior to rust-lang#93459, there was no memset but a full 280 bytes were being copied from the entry_ptr.

<table><tr><td>copy 280 bytes</td></tr></table>

This was not legal because not all of those bytes might be initialized, or even allocated, depending on the length of the directory entry's name, leading to a segfault. That PR fixed the segfault by creating a new zeroed dirent64 and copying just the guaranteed initialized prefix into it.

<table><tr><td>memset 280 bytes</td><td>copy 19 bytes</td></tr></table>

However this was still buggy because it used `addr_of!((*entry_ptr).d_name)`, which is considered UB by Miri in the case that the full extent of entry_ptr is not in bounds of the same allocation. (Arguably this shouldn't be a requirement, but here we are.)

The UB got fixed by rust-lang#94272 by replacing `addr_of` with some pointer manipulation based on `offset_from`, but still fundamentally the same operation.

<table><tr><td>memset 280 bytes</td><td>copy 19 bytes</td></tr></table>

Then rust-lang#94750 noticed that only 9 of those 19 bytes were even being used, so we could pick out only those 9 to put in the ReadDir value.

<table><tr><td>memset 280 bytes</td><td>copy 19 bytes</td><td>copy 9 bytes</td></tr></table>

After my PR we just grab the 9 needed bytes directly from entry_ptr.

<table><tr><td>copy 9 bytes</td></tr></table>

The resulting code is more complex but I believe still worthwhile to land for the following reason. This is an extremely straightforward thing to accomplish in C and clearly libc assumes that; literally just `entry_ptr->d_name`. The extra work in comparison to accomplish it in Rust is not an example of any actual safety being provided by Rust. I believe it's useful to have uncovered that and think about what could be done in the standard library or language to support this obvious operation better.

## References

- https://man7.org/linux/man-pages/man3/readdir.3.html
Aaron1011 pushed a commit to Aaron1011/rust that referenced this pull request Jan 6, 2023
Eliminate 280-byte memset from ReadDir iterator

This guy:

https://github.com/rust-lang/rust/blob/1536ab1b383f21b38f8d49230a2aecc51daffa3d/library/std/src/sys/unix/fs.rs#L589

It turns out `libc::dirent64` is quite big&mdash;https://docs.rs/libc/0.2.135/libc/struct.dirent64.html. In rust-lang#103135 this memset accounted for 0.9% of the runtime of iterating a big directory.

Almost none of the big zeroed value is ever used. We memcpy a tiny prefix (19 bytes) into it, and then read just 9 bytes (`d_ino` and `d_type`) back out. We can read exactly those 9 bytes we need directly from the original entry_ptr instead.

## History

This code got added in rust-lang#93459 and tweaked in rust-lang#94272 and rust-lang#94750.

Prior to rust-lang#93459, there was no memset but a full 280 bytes were being copied from the entry_ptr.

<table><tr><td>copy 280 bytes</td></tr></table>

This was not legal because not all of those bytes might be initialized, or even allocated, depending on the length of the directory entry's name, leading to a segfault. That PR fixed the segfault by creating a new zeroed dirent64 and copying just the guaranteed initialized prefix into it.

<table><tr><td>memset 280 bytes</td><td>copy 19 bytes</td></tr></table>

However this was still buggy because it used `addr_of!((*entry_ptr).d_name)`, which is considered UB by Miri in the case that the full extent of entry_ptr is not in bounds of the same allocation. (Arguably this shouldn't be a requirement, but here we are.)

The UB got fixed by rust-lang#94272 by replacing `addr_of` with some pointer manipulation based on `offset_from`, but still fundamentally the same operation.

<table><tr><td>memset 280 bytes</td><td>copy 19 bytes</td></tr></table>

Then rust-lang#94750 noticed that only 9 of those 19 bytes were even being used, so we could pick out only those 9 to put in the ReadDir value.

<table><tr><td>memset 280 bytes</td><td>copy 19 bytes</td><td>copy 9 bytes</td></tr></table>

After my PR we just grab the 9 needed bytes directly from entry_ptr.

<table><tr><td>copy 9 bytes</td></tr></table>

The resulting code is more complex but I believe still worthwhile to land for the following reason. This is an extremely straightforward thing to accomplish in C and clearly libc assumes that; literally just `entry_ptr->d_name`. The extra work in comparison to accomplish it in Rust is not an example of any actual safety being provided by Rust. I believe it's useful to have uncovered that and think about what could be done in the standard library or language to support this obvious operation better.

## References

- https://man7.org/linux/man-pages/man3/readdir.3.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants