about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-04-15 07:25:22 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-04-23 10:04:29 -0700
commitde7845ac72e01b491b4ed352f23c2c9a73efc45b (patch)
tree1b834db9811246cc36ac73f64a0584ac07702019
parentbb580f1a56138bd5a96ccc95c0f61caab72cf975 (diff)
downloadrust-de7845ac72e01b491b4ed352f23c2c9a73efc45b.tar.gz
rust-de7845ac72e01b491b4ed352f23c2c9a73efc45b.zip
rustc: Fix passing errors from LLVM to rustc
Many of the instances of setting a global error variable ended up leaving a
dangling pointer into free'd memory. This changes the method of error
transmission to strdup any error and "relinquish ownership" to rustc when it
gets an error. The corresponding Rust code will then free the error as
necessary.

Closes #12865
-rw-r--r--src/librustc/back/link.rs2
-rw-r--r--src/rustllvm/PassWrapper.cpp4
-rw-r--r--src/rustllvm/RustWrapper.cpp36
-rw-r--r--src/rustllvm/rustllvm.h2
4 files changed, 27 insertions, 17 deletions
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 9fd3894d794..f6846acaa99 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -60,7 +60,7 @@ pub fn llvm_err(sess: &Session, msg: ~str) -> ! {
         if cstr == ptr::null() {
             sess.fatal(msg);
         } else {
-            let err = CString::new(cstr, false);
+            let err = CString::new(cstr, true);
             let err = str::from_utf8_lossy(err.as_bytes());
             sess.fatal(msg + ": " + err.as_slice());
         }
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 32bac73debf..021dda49765 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -75,7 +75,7 @@ LLVMRustCreateTargetMachine(const char *triple,
     const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(),
                                                                  Error);
     if (TheTarget == NULL) {
-        LLVMRustError = Error.c_str();
+        LLVMRustSetLastError(Error.c_str());
         return NULL;
     }
 
@@ -178,7 +178,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
   raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary);
 #endif
   if (ErrorInfo != "") {
-    LLVMRustError = ErrorInfo.c_str();
+    LLVMRustSetLastError(ErrorInfo.c_str());
     return false;
   }
   formatted_raw_ostream FOS(OS);
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 3fe1b1380da..ec33b750358 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -23,18 +23,28 @@ using namespace llvm;
 using namespace llvm::sys;
 using namespace llvm::object;
 
-const char *LLVMRustError;
+static char *LastError;
 
 extern "C" LLVMMemoryBufferRef
 LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
   LLVMMemoryBufferRef MemBuf = NULL;
-  LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf,
-    const_cast<char **>(&LLVMRustError));
+  char *err = NULL;
+  LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf, &err);
+  if (err != NULL) {
+    LLVMRustSetLastError(err);
+  }
   return MemBuf;
 }
 
-extern "C" const char *LLVMRustGetLastError(void) {
-  return LLVMRustError;
+extern "C" char *LLVMRustGetLastError(void) {
+  char *ret = LastError;
+  LastError = NULL;
+  return ret;
+}
+
+void LLVMRustSetLastError(const char *err) {
+  free((void*) LastError);
+  LastError = strdup(err);
 }
 
 extern "C" void
@@ -609,14 +619,14 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
     MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
     ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
     if (!Src) {
-        LLVMRustError = Src.getError().message().c_str();
+        LLVMRustSetLastError(Src.getError().message().c_str());
         delete buf;
         return false;
     }
 
     std::string Err;
     if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
-        LLVMRustError = Err.c_str();
+        LLVMRustSetLastError(Err.c_str());
         return false;
     }
     return true;
@@ -629,13 +639,13 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
     std::string Err;
     Module *Src = llvm::getLazyBitcodeModule(buf, Dst->getContext(), &Err);
     if (!Src) {
-        LLVMRustError = Err.c_str();
+        LLVMRustSetLastError(Err.c_str());
         delete buf;
         return false;
     }
 
     if (Linker::LinkModules(Dst, Src, Linker::DestroySource, &Err)) {
-        LLVMRustError = Err.c_str();
+        LLVMRustSetLastError(Err.c_str());
         return false;
     }
     return true;
@@ -648,12 +658,12 @@ LLVMRustOpenArchive(char *path) {
     std::unique_ptr<MemoryBuffer> buf;
     error_code err = MemoryBuffer::getFile(path, buf);
     if (err) {
-        LLVMRustError = err.message().c_str();
+        LLVMRustSetLastError(err.message().c_str());
         return NULL;
     }
     Archive *ret = new Archive(buf.release(), err);
     if (err) {
-        LLVMRustError = err.message().c_str();
+        LLVMRustSetLastError(err.message().c_str());
         return NULL;
     }
     return ret;
@@ -664,12 +674,12 @@ LLVMRustOpenArchive(char *path) {
     OwningPtr<MemoryBuffer> buf;
     error_code err = MemoryBuffer::getFile(path, buf);
     if (err) {
-        LLVMRustError = err.message().c_str();
+        LLVMRustSetLastError(err.message().c_str());
         return NULL;
     }
     Archive *ret = new Archive(buf.take(), err);
     if (err) {
-        LLVMRustError = err.message().c_str();
+        LLVMRustSetLastError(err.message().c_str());
         return NULL;
     }
     return ret;
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index 42c60e72bab..5722eea48d7 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -68,4 +68,4 @@
 #include <unistd.h>
 #endif
 
-extern const char* LLVMRustError;
+void LLVMRustSetLastError(const char*);