Skip to content

Commit 09f9d02

Browse files
committed
cat: fix write error handling to propagate errors instead of panicking
The write helper functions (write_to_end, write_tab_to_end, write_nonprint_to_end) were using .unwrap() on write operations, which would cause a panic if writing failed. This changes them to return io::Result<usize> and use ? to properly propagate errors. Changes: - write_to_end: returns io::Result<usize>, uses ? instead of .unwrap() - write_tab_to_end: returns io::Result<usize>, uses ? instead of .unwrap() - write_nonprint_to_end: returns io::Result<usize>, uses ? instead of .unwrap() - write_end: returns io::Result<usize> to propagate errors from helpers - Updated call site in write_lines to handle the Result with ? - Updated unit tests to call .unwrap() on the Result Fixes #10016
1 parent 81ee8d1 commit 09f9d02

File tree

1 file changed

+26
-23
lines changed

1 file changed

+26
-23
lines changed

src/uu/cat/src/cat.rs

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ fn write_lines<R: FdReadable>(
565565
}
566566

567567
// print to end of line or end of buffer
568-
let offset = write_end(&mut writer, &in_buf[pos..], options);
568+
let offset = write_end(&mut writer, &in_buf[pos..], options)?;
569569

570570
// end of buffer?
571571
if offset + pos == in_buf.len() {
@@ -628,7 +628,11 @@ fn write_new_line<W: Write>(
628628
Ok(())
629629
}
630630

631-
fn write_end<W: Write>(writer: &mut W, in_buf: &[u8], options: &OutputOptions) -> usize {
631+
fn write_end<W: Write>(
632+
writer: &mut W,
633+
in_buf: &[u8],
634+
options: &OutputOptions,
635+
) -> io::Result<usize> {
632636
if options.show_nonprint {
633637
write_nonprint_to_end(in_buf, writer, options.tab().as_bytes())
634638
} else if options.show_tabs {
@@ -644,47 +648,47 @@ fn write_end<W: Write>(writer: &mut W, in_buf: &[u8], options: &OutputOptions) -
644648
// however, write_nonprint_to_end doesn't need to stop at \r because it will always write \r as ^M.
645649
// Return the number of written symbols
646650

647-
fn write_to_end<W: Write>(in_buf: &[u8], writer: &mut W) -> usize {
651+
fn write_to_end<W: Write>(in_buf: &[u8], writer: &mut W) -> io::Result<usize> {
648652
// using memchr2 significantly improves performances
649653
match memchr2(b'\n', b'\r', in_buf) {
650654
Some(p) => {
651-
writer.write_all(&in_buf[..p]).unwrap();
652-
p
655+
writer.write_all(&in_buf[..p])?;
656+
Ok(p)
653657
}
654658
None => {
655-
writer.write_all(in_buf).unwrap();
656-
in_buf.len()
659+
writer.write_all(in_buf)?;
660+
Ok(in_buf.len())
657661
}
658662
}
659663
}
660664

661-
fn write_tab_to_end<W: Write>(mut in_buf: &[u8], writer: &mut W) -> usize {
665+
fn write_tab_to_end<W: Write>(mut in_buf: &[u8], writer: &mut W) -> io::Result<usize> {
662666
let mut count = 0;
663667
loop {
664668
match in_buf
665669
.iter()
666670
.position(|c| *c == b'\n' || *c == b'\t' || *c == b'\r')
667671
{
668672
Some(p) => {
669-
writer.write_all(&in_buf[..p]).unwrap();
673+
writer.write_all(&in_buf[..p])?;
670674
if in_buf[p] == b'\t' {
671-
writer.write_all(b"^I").unwrap();
675+
writer.write_all(b"^I")?;
672676
in_buf = &in_buf[p + 1..];
673677
count += p + 1;
674678
} else {
675679
// b'\n' or b'\r'
676-
return count + p;
680+
return Ok(count + p);
677681
}
678682
}
679683
None => {
680-
writer.write_all(in_buf).unwrap();
681-
return in_buf.len() + count;
684+
writer.write_all(in_buf)?;
685+
return Ok(in_buf.len() + count);
682686
}
683687
}
684688
}
685689
}
686690

687-
fn write_nonprint_to_end<W: Write>(in_buf: &[u8], writer: &mut W, tab: &[u8]) -> usize {
691+
fn write_nonprint_to_end<W: Write>(in_buf: &[u8], writer: &mut W, tab: &[u8]) -> io::Result<usize> {
688692
let mut count = 0;
689693

690694
for byte in in_buf.iter().copied() {
@@ -699,11 +703,10 @@ fn write_nonprint_to_end<W: Write>(in_buf: &[u8], writer: &mut W, tab: &[u8]) ->
699703
128..=159 => writer.write_all(&[b'M', b'-', b'^', byte - 64]),
700704
160..=254 => writer.write_all(&[b'M', b'-', byte - 128]),
701705
_ => writer.write_all(b"M-^?"),
702-
}
703-
.unwrap();
706+
}?;
704707
count += 1;
705708
}
706-
count
709+
Ok(count)
707710
}
708711

709712
fn write_end_of_line<W: Write>(
@@ -733,22 +736,22 @@ mod tests {
733736
fn test_write_tab_to_end_with_newline() {
734737
let mut writer = BufWriter::with_capacity(1024 * 64, stdout());
735738
let in_buf = b"a\tb\tc\n";
736-
assert_eq!(super::write_tab_to_end(in_buf, &mut writer), 5);
739+
assert_eq!(super::write_tab_to_end(in_buf, &mut writer).unwrap(), 5);
737740
}
738741

739742
#[test]
740743
fn test_write_tab_to_end_no_newline() {
741744
let mut writer = BufWriter::with_capacity(1024 * 64, stdout());
742745
let in_buf = b"a\tb\tc";
743-
assert_eq!(super::write_tab_to_end(in_buf, &mut writer), 5);
746+
assert_eq!(super::write_tab_to_end(in_buf, &mut writer).unwrap(), 5);
744747
}
745748

746749
#[test]
747750
fn test_write_nonprint_to_end_new_line() {
748751
let mut writer = BufWriter::with_capacity(1024 * 64, stdout());
749752
let in_buf = b"\n";
750753
let tab = b"";
751-
super::write_nonprint_to_end(in_buf, &mut writer, tab);
754+
super::write_nonprint_to_end(in_buf, &mut writer, tab).unwrap();
752755
assert_eq!(writer.buffer().len(), 0);
753756
}
754757

@@ -757,7 +760,7 @@ mod tests {
757760
let mut writer = BufWriter::with_capacity(1024 * 64, stdout());
758761
let in_buf = &[9u8];
759762
let tab = b"tab";
760-
super::write_nonprint_to_end(in_buf, &mut writer, tab);
763+
super::write_nonprint_to_end(in_buf, &mut writer, tab).unwrap();
761764
assert_eq!(writer.buffer(), tab);
762765
}
763766

@@ -767,7 +770,7 @@ mod tests {
767770
let mut writer = BufWriter::with_capacity(1024 * 64, stdout());
768771
let in_buf = &[byte];
769772
let tab = b"";
770-
super::write_nonprint_to_end(in_buf, &mut writer, tab);
773+
super::write_nonprint_to_end(in_buf, &mut writer, tab).unwrap();
771774
assert_eq!(writer.buffer(), [b'^', byte + 64]);
772775
}
773776
}
@@ -778,7 +781,7 @@ mod tests {
778781
let mut writer = BufWriter::with_capacity(1024 * 64, stdout());
779782
let in_buf = &[byte];
780783
let tab = b"";
781-
super::write_nonprint_to_end(in_buf, &mut writer, tab);
784+
super::write_nonprint_to_end(in_buf, &mut writer, tab).unwrap();
782785
assert_eq!(writer.buffer(), [b'^', byte + 64]);
783786
}
784787
}

0 commit comments

Comments
 (0)