about summary refs log tree commit diff
path: root/compiler/rustc_serialize/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_serialize/src')
-rw-r--r--compiler/rustc_serialize/src/json.rs6
-rw-r--r--compiler/rustc_serialize/src/opaque.rs21
2 files changed, 20 insertions, 7 deletions
diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs
index df78e1bcbf6..cb9df3c3389 100644
--- a/compiler/rustc_serialize/src/json.rs
+++ b/compiler/rustc_serialize/src/json.rs
@@ -2320,12 +2320,12 @@ impl crate::Decoder for Decoder {
         let name = match self.pop() {
             Json::String(s) => s,
             Json::Object(mut o) => {
-                let n = match o.remove(&"variant".to_owned()) {
+                let n = match o.remove("variant") {
                     Some(Json::String(s)) => s,
                     Some(val) => return Err(ExpectedError("String".to_owned(), val.to_string())),
                     None => return Err(MissingFieldError("variant".to_owned())),
                 };
-                match o.remove(&"fields".to_string()) {
+                match o.remove("fields") {
                     Some(Json::Array(l)) => {
                         self.stack.extend(l.into_iter().rev());
                     }
@@ -2365,7 +2365,7 @@ impl crate::Decoder for Decoder {
     {
         let mut obj = expect!(self.pop(), Object)?;
 
-        let value = match obj.remove(&name.to_string()) {
+        let value = match obj.remove(name) {
             None => {
                 // Add a Null and try to parse it as an Option<_>
                 // to get None as a default value.
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 6e36184aff0..cc1216418ae 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -55,6 +55,13 @@ macro_rules! write_leb128 {
     }};
 }
 
+/// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string.
+/// This way we can skip validation and still be relatively sure that deserialization
+/// did not desynchronize.
+///
+/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout
+const STR_SENTINEL: u8 = 0xC1;
+
 impl serialize::Encoder for Encoder {
     type Error = !;
 
@@ -150,7 +157,8 @@ impl serialize::Encoder for Encoder {
     #[inline]
     fn emit_str(&mut self, v: &str) -> EncodeResult {
         self.emit_usize(v.len())?;
-        self.emit_raw_bytes(v.as_bytes())
+        self.emit_raw_bytes(v.as_bytes())?;
+        self.emit_u8(STR_SENTINEL)
     }
 
     #[inline]
@@ -502,7 +510,8 @@ impl serialize::Encoder for FileEncoder {
     #[inline]
     fn emit_str(&mut self, v: &str) -> FileEncodeResult {
         self.emit_usize(v.len())?;
-        self.emit_raw_bytes(v.as_bytes())
+        self.emit_raw_bytes(v.as_bytes())?;
+        self.emit_u8(STR_SENTINEL)
     }
 
     #[inline]
@@ -656,8 +665,12 @@ impl<'a> serialize::Decoder for Decoder<'a> {
     #[inline]
     fn read_str(&mut self) -> Result<Cow<'_, str>, Self::Error> {
         let len = self.read_usize()?;
-        let s = std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap();
-        self.position += len;
+        let sentinel = self.data[self.position + len];
+        assert!(sentinel == STR_SENTINEL);
+        let s = unsafe {
+            std::str::from_utf8_unchecked(&self.data[self.position..self.position + len])
+        };
+        self.position += len + 1;
         Ok(Cow::Borrowed(s))
     }