Skip to content

Commit 60f5011

Browse files
committed
auto merge of #8296 : erickt/rust/remove-str-trailing-nulls, r=erickt
This PR fixes #7235 and #3371, which removes trailing nulls from `str` types. Instead, it replaces the creation of c strings with a new type, `std::c_str::CString`, which wraps a malloced byte array, and respects: * No interior nulls * Ends with a trailing null
2 parents e81e81f + ee59aac commit 60f5011

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1236
-619
lines changed

src/libextra/rl.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// FIXME #3921. This is unsafe because linenoise uses global mutable
1212
// state without mutexes.
1313

14-
14+
use std::c_str::ToCStr;
1515
use std::libc::{c_char, c_int};
1616
use std::local_data;
1717
use std::str;
@@ -32,7 +32,7 @@ pub mod rustrt {
3232

3333
/// Add a line to history
3434
pub unsafe fn add_history(line: &str) -> bool {
35-
do line.as_c_str |buf| {
35+
do line.to_c_str().with_ref |buf| {
3636
rustrt::linenoiseHistoryAdd(buf) == 1 as c_int
3737
}
3838
}
@@ -44,21 +44,21 @@ pub unsafe fn set_history_max_len(len: int) -> bool {
4444

4545
/// Save line history to a file
4646
pub unsafe fn save_history(file: &str) -> bool {
47-
do file.as_c_str |buf| {
47+
do file.to_c_str().with_ref |buf| {
4848
rustrt::linenoiseHistorySave(buf) == 1 as c_int
4949
}
5050
}
5151

5252
/// Load line history from a file
5353
pub unsafe fn load_history(file: &str) -> bool {
54-
do file.as_c_str |buf| {
54+
do file.to_c_str().with_ref |buf| {
5555
rustrt::linenoiseHistoryLoad(buf) == 1 as c_int
5656
}
5757
}
5858

5959
/// Print out a prompt and then wait for input and return it
6060
pub unsafe fn read(prompt: &str) -> Option<~str> {
61-
do prompt.as_c_str |buf| {
61+
do prompt.to_c_str().with_ref |buf| {
6262
let line = rustrt::linenoise(buf);
6363

6464
if line.is_null() { None }
@@ -80,7 +80,7 @@ pub unsafe fn complete(cb: CompletionCb) {
8080

8181
unsafe {
8282
do cb(str::raw::from_c_str(line)) |suggestion| {
83-
do suggestion.as_c_str |buf| {
83+
do suggestion.to_c_str().with_ref |buf| {
8484
rustrt::linenoiseAddCompletion(completions, buf);
8585
}
8686
}

src/libextra/terminfo/parm.rs

+98-2
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ impl FormatOp {
476476
}
477477
}
478478

479+
#[cfg(stage0)]
479480
fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
480481
let mut s = match val {
481482
Number(d) => {
@@ -545,8 +546,103 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
545546
String(s) => {
546547
match op {
547548
FormatString => {
548-
let mut s = s.to_bytes_with_null();
549-
s.pop(); // remove the null
549+
let mut s = s.as_bytes().to_owned();
550+
if flags.precision > 0 && flags.precision < s.len() {
551+
s.truncate(flags.precision);
552+
}
553+
s
554+
}
555+
_ => {
556+
return Err(fmt!("non-string on stack with %%%c", op.to_char()))
557+
}
558+
}
559+
}
560+
};
561+
if flags.width > s.len() {
562+
let n = flags.width - s.len();
563+
if flags.left {
564+
s.grow(n, &(' ' as u8));
565+
} else {
566+
let mut s_ = vec::with_capacity(flags.width);
567+
s_.grow(n, &(' ' as u8));
568+
s_.push_all_move(s);
569+
s = s_;
570+
}
571+
}
572+
Ok(s)
573+
}
574+
575+
#[cfg(not(stage0))]
576+
fn format(val: Param, op: FormatOp, flags: Flags) -> Result<~[u8],~str> {
577+
let mut s = match val {
578+
Number(d) => {
579+
match op {
580+
FormatString => {
581+
return Err(~"non-number on stack with %s")
582+
}
583+
_ => {
584+
let radix = match op {
585+
FormatDigit => 10,
586+
FormatOctal => 8,
587+
FormatHex|FormatHEX => 16,
588+
FormatString => util::unreachable()
589+
};
590+
let mut s = ~[];
591+
match op {
592+
FormatDigit => {
593+
let sign = if flags.sign { SignAll } else { SignNeg };
594+
do int_to_str_bytes_common(d, radix, sign) |c| {
595+
s.push(c);
596+
}
597+
}
598+
_ => {
599+
do int_to_str_bytes_common(d as uint, radix, SignNone) |c| {
600+
s.push(c);
601+
}
602+
}
603+
};
604+
if flags.precision > s.len() {
605+
let mut s_ = vec::with_capacity(flags.precision);
606+
let n = flags.precision - s.len();
607+
s_.grow(n, &('0' as u8));
608+
s_.push_all_move(s);
609+
s = s_;
610+
}
611+
assert!(!s.is_empty(), "string conversion produced empty result");
612+
match op {
613+
FormatDigit => {
614+
if flags.space && !(s[0] == '-' as u8 || s[0] == '+' as u8) {
615+
s.unshift(' ' as u8);
616+
}
617+
}
618+
FormatOctal => {
619+
if flags.alternate && s[0] != '0' as u8 {
620+
s.unshift('0' as u8);
621+
}
622+
}
623+
FormatHex => {
624+
if flags.alternate {
625+
let s_ = util::replace(&mut s, ~['0' as u8, 'x' as u8]);
626+
s.push_all_move(s_);
627+
}
628+
}
629+
FormatHEX => {
630+
s = s.into_ascii().to_upper().into_bytes();
631+
if flags.alternate {
632+
let s_ = util::replace(&mut s, ~['0' as u8, 'X' as u8]);
633+
s.push_all_move(s_);
634+
}
635+
}
636+
FormatString => util::unreachable()
637+
}
638+
s
639+
}
640+
}
641+
}
642+
String(s) => {
643+
match op {
644+
FormatString => {
645+
let mut s = s.as_bytes().to_owned();
550646
if flags.precision > 0 && flags.precision < s.len() {
551647
s.truncate(flags.precision);
552648
}

src/libextra/time.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,14 @@ fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> {
284284
fn match_digits(ss: &str, pos: uint, digits: uint, ws: bool)
285285
-> Option<(i32, uint)> {
286286
let mut pos = pos;
287+
let len = ss.len();
287288
let mut value = 0_i32;
288289

289290
let mut i = 0u;
290291
while i < digits {
292+
if pos >= len {
293+
return None;
294+
}
291295
let range = ss.char_range_at(pos);
292296
pos = range.next;
293297

@@ -853,7 +857,7 @@ fn do_strftime(format: &str, tm: &Tm) -> ~str {
853857

854858
#[cfg(test)]
855859
mod tests {
856-
use time::*;
860+
use super::*;
857861

858862
use std::float;
859863
use std::os;
@@ -901,7 +905,7 @@ mod tests {
901905
os::setenv("TZ", "America/Los_Angeles");
902906
tzset();
903907

904-
let time = ::time::Timespec::new(1234567890, 54321);
908+
let time = Timespec::new(1234567890, 54321);
905909
let utc = at_utc(time);
906910

907911
assert!(utc.tm_sec == 30_i32);
@@ -922,7 +926,7 @@ mod tests {
922926
os::setenv("TZ", "America/Los_Angeles");
923927
tzset();
924928
925-
let time = ::time::Timespec::new(1234567890, 54321);
929+
let time = Timespec::new(1234567890, 54321);
926930
let local = at(time);
927931
928932
error!("time_at: %?", local);
@@ -950,7 +954,7 @@ mod tests {
950954
os::setenv("TZ", "America/Los_Angeles");
951955
tzset();
952956
953-
let time = ::time::Timespec::new(1234567890, 54321);
957+
let time = Timespec::new(1234567890, 54321);
954958
let utc = at_utc(time);
955959
956960
assert_eq!(utc.to_timespec(), time);
@@ -961,7 +965,7 @@ mod tests {
961965
os::setenv("TZ", "America/Los_Angeles");
962966
tzset();
963967
964-
let time = ::time::Timespec::new(1234567890, 54321);
968+
let time = Timespec::new(1234567890, 54321);
965969
let utc = at_utc(time);
966970
let local = at(time);
967971
@@ -1142,7 +1146,7 @@ mod tests {
11421146
os::setenv("TZ", "America/Los_Angeles");
11431147
tzset();
11441148
1145-
let time = ::time::Timespec::new(1234567890, 54321);
1149+
let time = Timespec::new(1234567890, 54321);
11461150
let utc = at_utc(time);
11471151
let local = at(time);
11481152
@@ -1156,7 +1160,7 @@ mod tests {
11561160
os::setenv("TZ", "America/Los_Angeles");
11571161
tzset();
11581162
1159-
let time = ::time::Timespec::new(1234567890, 54321);
1163+
let time = Timespec::new(1234567890, 54321);
11601164
let utc = at_utc(time);
11611165
let local = at(time);
11621166

src/librustc/back/link.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use middle::trans::common::gensym_name;
2222
use middle::ty;
2323
use util::ppaux;
2424

25+
use std::c_str::ToCStr;
2526
use std::char;
2627
use std::hash::Streaming;
2728
use std::hash;
@@ -76,9 +77,9 @@ pub fn WriteOutputFile(sess: Session,
7677
OptLevel: c_int,
7778
EnableSegmentedStacks: bool) {
7879
unsafe {
79-
do Triple.as_c_str |Triple| {
80-
do Feature.as_c_str |Feature| {
81-
do Output.as_c_str |Output| {
80+
do Triple.to_c_str().with_ref |Triple| {
81+
do Feature.to_c_str().with_ref |Feature| {
82+
do Output.to_c_str().with_ref |Output| {
8283
let result = llvm::LLVMRustWriteOutputFile(
8384
PM,
8485
M,
@@ -105,6 +106,7 @@ pub mod jit {
105106
use lib::llvm::{ModuleRef, ContextRef, ExecutionEngineRef};
106107
use metadata::cstore;
107108

109+
use std::c_str::ToCStr;
108110
use std::cast;
109111
use std::local_data;
110112
use std::unstable::intrinsics;
@@ -146,7 +148,7 @@ pub mod jit {
146148

147149
debug!("linking: %s", path);
148150

149-
do path.as_c_str |buf_t| {
151+
do path.to_c_str().with_ref |buf_t| {
150152
if !llvm::LLVMRustLoadCrate(manager, buf_t) {
151153
llvm_err(sess, ~"Could not link");
152154
}
@@ -165,7 +167,7 @@ pub mod jit {
165167
// Next, we need to get a handle on the _rust_main function by
166168
// looking up it's corresponding ValueRef and then requesting that
167169
// the execution engine compiles the function.
168-
let fun = do "_rust_main".as_c_str |entry| {
170+
let fun = do "_rust_main".to_c_str().with_ref |entry| {
169171
llvm::LLVMGetNamedFunction(m, entry)
170172
};
171173
if fun.is_null() {
@@ -230,6 +232,7 @@ pub mod write {
230232

231233
use back::passes;
232234

235+
use std::c_str::ToCStr;
233236
use std::libc::{c_int, c_uint};
234237
use std::path::Path;
235238
use std::run;
@@ -263,14 +266,14 @@ pub mod write {
263266
output_type_bitcode => {
264267
if opts.optimize != session::No {
265268
let filename = output.with_filetype("no-opt.bc");
266-
do filename.to_str().as_c_str |buf| {
269+
do filename.to_c_str().with_ref |buf| {
267270
llvm::LLVMWriteBitcodeToFile(llmod, buf);
268271
}
269272
}
270273
}
271274
_ => {
272275
let filename = output.with_filetype("bc");
273-
do filename.to_str().as_c_str |buf| {
276+
do filename.to_c_str().with_ref |buf| {
274277
llvm::LLVMWriteBitcodeToFile(llmod, buf);
275278
}
276279
}
@@ -333,7 +336,7 @@ pub mod write {
333336
// Always output the bitcode file with --save-temps
334337

335338
let filename = output.with_filetype("opt.bc");
336-
do filename.to_str().as_c_str |buf| {
339+
do filename.to_c_str().with_ref |buf| {
337340
llvm::LLVMWriteBitcodeToFile(llmod, buf)
338341
};
339342
// Save the assembly file if -S is used
@@ -391,13 +394,13 @@ pub mod write {
391394

392395
if output_type == output_type_llvm_assembly {
393396
// Given options "-S --emit-llvm": output LLVM assembly
394-
do output.to_str().as_c_str |buf_o| {
397+
do output.to_c_str().with_ref |buf_o| {
395398
llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o);
396399
}
397400
} else {
398401
// If only a bitcode file is asked for by using the
399402
// '--emit-llvm' flag, then output it here
400-
do output.to_str().as_c_str |buf| {
403+
do output.to_c_str().with_ref |buf| {
401404
llvm::LLVMWriteBitcodeToFile(llmod, buf);
402405
}
403406
}

src/librustc/back/passes.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::c_str::ToCStr;
1112
use std::io;
1213

1314
use driver::session::{OptLevel, No, Less, Aggressive};
@@ -172,7 +173,7 @@ pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~s
172173
}
173174

174175
pub fn create_pass(name:&str) -> Option<PassRef> {
175-
do name.as_c_str |s| {
176+
do name.to_c_str().with_ref |s| {
176177
unsafe {
177178
let p = llvm::LLVMCreatePass(s);
178179
if p.is_null() {

src/librustc/lib/llvm.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
11+
use std::c_str::ToCStr;
1212
use std::hashmap::HashMap;
1313
use std::libc::{c_uint, c_ushort};
1414
use std::option;
@@ -2259,7 +2259,7 @@ pub struct TargetData {
22592259
}
22602260

22612261
pub fn mk_target_data(string_rep: &str) -> TargetData {
2262-
let lltd = do string_rep.as_c_str |buf| {
2262+
let lltd = do string_rep.to_c_str().with_ref |buf| {
22632263
unsafe { llvm::LLVMCreateTargetData(buf) }
22642264
};
22652265

src/librustc/metadata/loader.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use syntax::print::pprust;
2323
use syntax::{ast, attr};
2424
use syntax::attr::AttrMetaMethods;
2525

26+
use std::c_str::ToCStr;
2627
use std::cast;
2728
use std::io;
2829
use std::num;
@@ -198,7 +199,7 @@ pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
198199
fn get_metadata_section(os: os,
199200
filename: &Path) -> Option<@~[u8]> {
200201
unsafe {
201-
let mb = do filename.to_str().as_c_str |buf| {
202+
let mb = do filename.to_c_str().with_ref |buf| {
202203
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
203204
};
204205
if mb as int == 0 { return option::None::<@~[u8]>; }

0 commit comments

Comments
 (0)