From 1d51b1649e75b8d2e8ca81c9aab08c9f119a6ab5 Mon Sep 17 00:00:00 2001 From: Aaron O'Mullan Date: Sun, 1 May 2022 19:13:05 -0700 Subject: fix(runtime): lossy utf8 readTextFile (#14456) --- runtime/ops/fs.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'runtime') diff --git a/runtime/ops/fs.rs b/runtime/ops/fs.rs index 501c2ac5f..99b37916d 100644 --- a/runtime/ops/fs.rs +++ b/runtime/ops/fs.rs @@ -21,6 +21,7 @@ use deno_crypto::rand::Rng; use log::debug; use serde::Deserialize; use serde::Serialize; +use std::borrow::Cow; use std::cell::RefCell; use std::convert::From; use std::env::{current_dir, set_current_dir, temp_dir}; @@ -2032,7 +2033,7 @@ fn op_readfile_text_sync( let permissions = state.borrow_mut::(); let path = Path::new(&path); permissions.read.check(path)?; - Ok(std::fs::read_to_string(path)?) + Ok(string_from_utf8_lossy(std::fs::read(path)?)) } #[op] @@ -2075,7 +2076,7 @@ async fn op_readfile_text_async( } let fut = tokio::task::spawn_blocking(move || { let path = Path::new(&path); - Ok(String::from_utf8(std::fs::read(path)?)?) + Ok(string_from_utf8_lossy(std::fs::read(path)?)) }); if let Some(cancel_rid) = cancel_rid { let cancel_handle = state @@ -2088,3 +2089,14 @@ async fn op_readfile_text_async( } fut.await? } + +// Like String::from_utf8_lossy but operates on owned values +fn string_from_utf8_lossy(buf: Vec) -> String { + match String::from_utf8_lossy(&buf) { + // buf contained non-utf8 chars than have been patched + Cow::Owned(s) => s, + // SAFETY: if Borrowed then the buf only contains utf8 chars, + // we do this instead of .into_owned() to avoid copying the input buf + Cow::Borrowed(_) => unsafe { String::from_utf8_unchecked(buf) }, + } +} -- cgit v1.2.3