Skip to content

Commit 908dba0

Browse files
committed
Auto merge of #38048 - rkruppe:llvm-stringref-fixes, r=alexcrichton
[LLVM 4.0] Don't assume llvm::StringRef is null terminated StringRefs have a length and their contents are not usually null-terminated. The solution is to either copy the string data (in `rustc_llvm::diagnostic`) or take the size into account (in LLVMRustPrintPasses). I couldn't trigger a bug caused by this (apparently all the strings returned in practice are actually null-terminated) but this is more correct and more future-proof. cc #37609
2 parents 149e76f + 85dc08e commit 908dba0

File tree

5 files changed

+26
-28
lines changed

5 files changed

+26
-28
lines changed

src/librustc_llvm/diagnostic.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
pub use self::OptimizationDiagnosticKind::*;
1414
pub use self::Diagnostic::*;
1515

16-
use libc::{c_char, c_uint};
16+
use libc::c_uint;
1717
use std::ptr;
1818

1919
use {DiagnosticInfoRef, TwineRef, ValueRef};
@@ -45,7 +45,7 @@ impl OptimizationDiagnosticKind {
4545

4646
pub struct OptimizationDiagnostic {
4747
pub kind: OptimizationDiagnosticKind,
48-
pub pass_name: *const c_char,
48+
pub pass_name: String,
4949
pub function: ValueRef,
5050
pub debug_loc: DebugLocRef,
5151
pub message: String,
@@ -55,21 +55,23 @@ impl OptimizationDiagnostic {
5555
unsafe fn unpack(kind: OptimizationDiagnosticKind,
5656
di: DiagnosticInfoRef)
5757
-> OptimizationDiagnostic {
58-
let mut pass_name = ptr::null();
5958
let mut function = ptr::null_mut();
6059
let mut debug_loc = ptr::null_mut();
6160

62-
let message = super::build_string(|message|
63-
super::LLVMRustUnpackOptimizationDiagnostic(di,
64-
&mut pass_name,
65-
&mut function,
66-
&mut debug_loc,
67-
message)
61+
let mut message = None;
62+
let pass_name = super::build_string(|pass_name|
63+
message = super::build_string(|message|
64+
super::LLVMRustUnpackOptimizationDiagnostic(di,
65+
pass_name,
66+
&mut function,
67+
&mut debug_loc,
68+
message)
69+
)
6870
);
6971

7072
OptimizationDiagnostic {
7173
kind: kind,
72-
pass_name: pass_name,
74+
pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"),
7375
function: function,
7476
debug_loc: debug_loc,
7577
message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM")

src/librustc_llvm/ffi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1820,7 +1820,7 @@ extern "C" {
18201820
DiagnosticContext: *mut c_void);
18211821

18221822
pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef,
1823-
pass_name_out: *mut *const c_char,
1823+
pass_name_out: RustStringRef,
18241824
function_out: *mut ValueRef,
18251825
debugloc_out: *mut DebugLocRef,
18261826
message_out: RustStringRef);

src/librustc_trans/back/write.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use errors::emitter::Emitter;
2626
use syntax_pos::MultiSpan;
2727
use context::{is_pie_binary, get_reloc_model};
2828

29-
use std::ffi::{CStr, CString};
29+
use std::ffi::CString;
3030
use std::fs;
3131
use std::path::{Path, PathBuf};
3232
use std::str;
@@ -403,19 +403,16 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo
403403
}
404404

405405
llvm::diagnostic::Optimization(opt) => {
406-
let pass_name = str::from_utf8(CStr::from_ptr(opt.pass_name).to_bytes())
407-
.ok()
408-
.expect("got a non-UTF8 pass name from LLVM");
409406
let enabled = match cgcx.remark {
410407
AllPasses => true,
411-
SomePasses(ref v) => v.iter().any(|s| *s == pass_name),
408+
SomePasses(ref v) => v.iter().any(|s| *s == opt.pass_name),
412409
};
413410

414411
if enabled {
415412
let loc = llvm::debug_loc_to_string(llcx, opt.debug_loc);
416413
cgcx.handler.note_without_error(&format!("optimization {} for {} at {}: {}",
417414
opt.kind.describe(),
418-
pass_name,
415+
opt.pass_name,
419416
if loc.is_empty() { "[unknown]" } else { &*loc },
420417
opt.message));
421418
}

src/rustllvm/PassWrapper.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,11 @@ LLVMRustPrintPasses() {
530530
struct MyListener : PassRegistrationListener {
531531
void passEnumerate(const PassInfo *info) {
532532
#if LLVM_VERSION_GE(4, 0)
533-
if (!info->getPassArgument().empty()) {
534-
printf("%15s - %s\n", info->getPassArgument().data(),
535-
info->getPassName().data());
533+
StringRef PassArg = info->getPassArgument();
534+
StringRef PassName = info->getPassName();
535+
if (!PassArg.empty()) {
536+
printf("%15.*s - %.*s\n", PassArg.size(), PassArg.data(),
537+
PassName.size(), PassName.data());
536538
}
537539
#else
538540
if (info->getPassArgument() && *info->getPassArgument()) {

src/rustllvm/RustWrapper.cpp

+5-8
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
872872
extern "C" void
873873
LLVMRustUnpackOptimizationDiagnostic(
874874
LLVMDiagnosticInfoRef di,
875-
const char **pass_name_out,
875+
RustStringRef pass_name_out,
876876
LLVMValueRef *function_out,
877877
LLVMDebugLocRef *debugloc_out,
878878
RustStringRef message_out)
@@ -881,15 +881,12 @@ LLVMRustUnpackOptimizationDiagnostic(
881881
llvm::DiagnosticInfoOptimizationBase *opt
882882
= static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
883883

884-
#if LLVM_VERSION_GE(4, 0)
885-
*pass_name_out = opt->getPassName().data();
886-
#else
887-
*pass_name_out = opt->getPassName();
888-
#endif
884+
raw_rust_string_ostream pass_name_os(pass_name_out);
885+
pass_name_os << opt->getPassName();
889886
*function_out = wrap(&opt->getFunction());
890887
*debugloc_out = wrap(&opt->getDebugLoc());
891-
raw_rust_string_ostream os(message_out);
892-
os << opt->getMsg();
888+
raw_rust_string_ostream message_os(message_out);
889+
message_os << opt->getMsg();
893890
}
894891

895892
extern "C" void

0 commit comments

Comments
 (0)