mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
fix(runtime): lossy utf8 readTextFile (#14456)
This commit is contained in:
parent
3d9aecfa7a
commit
2080ea6f52
2 changed files with 30 additions and 2 deletions
|
@ -791,3 +791,19 @@ Deno.test(
|
|||
assertEquals(res, "hello world!");
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, write: true } },
|
||||
async function readTextFileNonUtf8() {
|
||||
const path = await Deno.makeTempFile();
|
||||
const file = await Deno.open(path, { write: true });
|
||||
await file.write(new TextEncoder().encode("hello "));
|
||||
await file.write(new Uint8Array([0xC0]));
|
||||
file.close();
|
||||
|
||||
const res = await Deno.readTextFile(path);
|
||||
const resSync = Deno.readTextFileSync(path);
|
||||
assertEquals(res, resSync);
|
||||
assertEquals(res, "hello \uFFFD");
|
||||
},
|
||||
);
|
||||
|
|
|
@ -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::<Permissions>();
|
||||
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<u8>) -> 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) },
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue