mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-10 13:01:29 +00:00
fix(engine): open linked documents without blocking and check the handle is a regular file (#5982)
This commit is contained in:
1 parent
3fe86a118e
commit
8f29ed66f9
1 file changed
+19
-1
@@ -227,7 +227,25 @@ pub fn read_remote_document(path: &Path) -> Result<Vec<u8>, RemoteDocumentPathEr
|
||||
if meta.len() > MAX_REMOTE_DOCUMENT_BYTES {
|
||||
return Err(RemoteDocumentPathError::TooLarge);
|
||||
}
|
||||
let file = std::fs::File::open(path).map_err(|e| RemoteDocumentPathError::Read(e.to_string()))?;
|
||||
// The path can change between that check and the open (a file replaced by a FIFO): opened
|
||||
// without blocking, and checked again on the handle, which is what is read.
|
||||
let mut options = std::fs::OpenOptions::new();
|
||||
options.read(true);
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::OpenOptionsExt as _;
|
||||
// O_NONBLOCK: Linux 0o4000, macOS and the BSDs 0x4.
|
||||
options.custom_flags(if cfg!(target_os = "linux") { 0o4000 } else { 0x4 });
|
||||
}
|
||||
let file = options.open(path).map_err(|e| RemoteDocumentPathError::Read(e.to_string()))?;
|
||||
let meta = file.metadata().map_err(|e| RemoteDocumentPathError::Read(e.to_string()))?;
|
||||
if !meta.is_file() {
|
||||
return Err(RemoteDocumentPathError::NotAFile);
|
||||
}
|
||||
// the opened handle's own length: a file replaced after the path check must not size the buffer
|
||||
if meta.len() > MAX_REMOTE_DOCUMENT_BYTES {
|
||||
return Err(RemoteDocumentPathError::TooLarge);
|
||||
}
|
||||
let mut bytes = Vec::with_capacity(usize::try_from(meta.len()).unwrap_or(0));
|
||||
file.take(MAX_REMOTE_DOCUMENT_BYTES.saturating_add(1)).read_to_end(&mut bytes).map_err(|e| RemoteDocumentPathError::Read(e.to_string()))?;
|
||||
if u64::try_from(bytes.len()).map_or(true, |n| n > MAX_REMOTE_DOCUMENT_BYTES) {
|
||||
|
||||
Reference in new issue
Block a user