Skip to content

Commit 5f2fd98

Browse files
committed
fix: use OwnedFd in parse_fd for I/O safety
1 parent a51c769 commit 5f2fd98

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

librdb/src/parser.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
use std::{ffi::CString, marker::PhantomData, os::fd::RawFd, path::Path, ptr};
1+
use std::{
2+
ffi::CString,
3+
marker::PhantomData,
4+
os::fd::{IntoRawFd, OwnedFd},
5+
path::Path,
6+
ptr,
7+
};
28

39
use librdb_sys::{
410
self, RdbHandlersDataCallbacks, RdbStatus_RDB_STATUS_ERROR, RdbStatus_RDB_STATUS_OK,
@@ -116,27 +122,26 @@ impl<H: RdbHandlers> Parser<H> {
116122
self.run_parse()
117123
}
118124

119-
/// Attach a file-descriptor reader and parse the RDB data.
125+
/// Parse RDB data from a file descriptor.
120126
///
121-
/// If `close_when_done` is true, librdb will close the fd after parsing.
122-
/// The fd must be in blocking mode.
127+
/// Takes ownership of the fd. The fd must be in blocking mode.
123128
///
124129
/// # Errors
125130
/// Returns an error if the reader cannot be created, the RDB data is
126131
/// malformed, or a handler callback returns `Err`.
127-
pub fn parse_fd(&mut self, fd: RawFd, close_when_done: bool) -> Result<()> {
132+
pub fn parse_fd(&mut self, fd: OwnedFd) -> Result<()> {
128133
if self.parsed {
129134
return Err(RdbError::Parser {
130135
code: 0,
131136
message: "parser already used; create a new Parser instance".into(),
132137
});
133138
}
134139

135-
// SAFETY: self.raw is a valid parser in CONFIGURING state. The caller
136-
// is responsible for providing a valid, blocking fd.
137-
let reader = unsafe {
138-
librdb_sys::RDBX_createReaderFileDesc(self.raw, fd, i32::from(close_when_done))
139-
};
140+
// SAFETY: self.raw is a valid parser in CONFIGURING state.
141+
// OwnedFd guarantees a valid fd; into_raw_fd transfers ownership to
142+
// librdb which will close it (fdCloseWhenDone = 1).
143+
let raw_fd = fd.into_raw_fd();
144+
let reader = unsafe { librdb_sys::RDBX_createReaderFileDesc(self.raw, raw_fd, 1) };
140145
if reader.is_null() {
141146
return Err(self.extract_c_error("RDBX_createReaderFileDesc returned null"));
142147
}

librdb/tests/level2.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,13 +647,11 @@ fn empty_rdb() {
647647
#[test]
648648
fn parse_fd_single_key() {
649649
use std::fs::File;
650-
use std::os::fd::IntoRawFd;
651650

652651
let file = File::open(fixture("single_key.rdb")).expect("open fixture");
653-
let fd = file.into_raw_fd(); // transfer ownership to librdb
654652

655653
let mut parser = Parser::new(Collector::default()).expect("create parser");
656-
parser.parse_fd(fd, true).expect("parse");
654+
parser.parse_fd(file.into()).expect("parse");
657655
let events = parser.into_handler().events;
658656

659657
let keys = keys_of(&events);

0 commit comments

Comments
 (0)