{"action":"created","issue":{"url":"https://api.github.com/repos/rust-lang/rust/issues/20475","labels_url":"https://api.github.com/repos/rust-lang/rust/issues/20475/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/20475/comments","events_url":"https://api.github.com/repos/rust-lang/rust/issues/20475/events","html_url":"https://github.com/rust-lang/rust/issues/20475","id":53307321,"number":20475,"title":"CString should have a \"within max length\" constructor","user":{"login":"shepmaster","id":174509,"avatar_url":"https://avatars.githubusercontent.com/u/174509?v=3","gravatar_id":"","url":"https://api.github.com/users/shepmaster","html_url":"https://github.com/shepmaster","followers_url":"https://api.github.com/users/shepmaster/followers","following_url":"https://api.github.com/users/shepmaster/following{/other_user}","gists_url":"https://api.github.com/users/shepmaster/gists{/gist_id}","starred_url":"https://api.github.com/users/shepmaster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shepmaster/subscriptions","organizations_url":"https://api.github.com/users/shepmaster/orgs","repos_url":"https://api.github.com/users/shepmaster/repos","events_url":"https://api.github.com/users/shepmaster/events{/privacy}","received_events_url":"https://api.github.com/users/shepmaster/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rust-lang/rust/labels/A-ffi","name":"A-ffi","color":"d7e102"},{"url":"https://api.github.com/repos/rust-lang/rust/labels/A-libs","name":"A-libs","color":"d7e102"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-01-03T15:53:52Z","updated_at":"2015-01-05T07:17:20Z","closed_at":null,"body":"[This Stack Overflow question](http://stackoverflow.com/q/27751137/155423) points out this relatively-common C idiom (trimmed down to show the interesting bits):\r\n\r\n```rust\r\nlet mut errbuf = [0 as c_char, ..256];\r\nc_function_that_fails(errbuf.as_mut_ptr() as *mut libc::c_char);\r\nCString::new(errbuf.as_ptr(), false);\r\n```\r\n\r\nThe questioner wonders about the case where `errbuf` is not correctly set and no `NUL` bytes occur in the buffer. When we go to use the string, we might merrily walk our way through memory! Since we know the length of `errbuf`, we should be able to check that there is a `NUL` in the first X bytes and fail otherwise.\r\n\r\nWhile looking to see how Rust handles this case, I found the following spots that could suffer from the same problem:\r\n\r\n- [net.rs](https://github.com/rust-lang/rust/blob/c89417130f042c58adc60012e7cddc4ef70b70b9/src/libstd/sys/common/net.rs#L307-L329)\r\n- [unix/os.rs](https://github.com/rust-lang/rust/blob/c89417130f042c58adc60012e7cddc4ef70b70b9/src/libstd/sys/unix/os.rs#L91-L114)\r\n- [unix/os.rs](https://github.com/rust-lang/rust/blob/c89417130f042c58adc60012e7cddc4ef70b70b9/src/libstd/sys/unix/os.rs#L125-L136)\r\n- [windows/backtrace.rs](https://github.com/rust-lang/rust/blob/c89417130f042c58adc60012e7cddc4ef70b70b9/src/libstd/sys/windows/backtrace.rs#L360)\r\n\r\nI propose we add a new constructor to `CString`: `of_max_len`. This would make sure that a `NUL` byte occurs within a certain number of bytes. If it doesn't, we `panic!`.\r\n\r\nI think we could also make *this* particular case easier with a constructor like `from_slice`, which could be passed the slice which would implicitly know its length.\r\n\r\nI'm more than welcome to feedback of all kinds!"},"comment":{"url":"https://api.github.com/repos/rust-lang/rust/issues/comments/68675281","html_url":"https://github.com/rust-lang/rust/issues/20475#issuecomment-68675281","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/20475","id":68675281,"user":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars.githubusercontent.com/u/64996?v=3","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"created_at":"2015-01-05T07:17:20Z","updated_at":"2015-01-05T07:17:20Z","body":"Note that one idea I had on https://github.com/rust-lang/rust/pull/20507 was that this use case could be handled with `slice::from_raw_buf` because the length is known so it can be converted to a slice immediately (and then a find for the 0 and slice afterwards).\r\n\r\n@chrish42 for your use cases I would expect:\r\n\r\n1. This should in theory be handled with a small vector optimization which can store data inline in the `CString` itself (which now uses `Vec` internally).\r\n2. You can currently do that today with `let mut buf = [0; LEN]; foo(buf.as_mut_ptr(), buf.len());`, I don't think we need to involve `CString` with that.\r\n3. I think that this is the use case for this bug, which may be solvable with my idea above."}}