1
0
Fork 0
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:
Aaron O'Mullan 2022-05-01 19:13:05 -07:00 committed by cjihrig
parent 3d9aecfa7a
commit 2080ea6f52
No known key found for this signature in database
GPG key ID: 7434390BDBE9B9C5
2 changed files with 30 additions and 2 deletions

View file

@ -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");
},
);

View file

@ -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) },
}
}