Skip to content

Commit bb58e6c

Browse files
authored
Merge pull request serde-rs#525 from 17dec/eof-numbers
Return EOF on truncated numbers
2 parents e6b02d1 + 69bfbfc commit bb58e6c

File tree

3 files changed

+62
-12
lines changed

3 files changed

+62
-12
lines changed

src/de.rs

+28-8
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,14 @@ impl<'de, R: Read<'de>> Deserializer<R> {
380380
}
381381

382382
fn parse_integer(&mut self, positive: bool) -> Result<ParserNumber> {
383-
match try!(self.next_char_or_null()) {
383+
let next = match try!(self.next_char()) {
384+
Some(b) => b,
385+
None => {
386+
return Err(self.error(ErrorCode::EofWhileParsingValue));
387+
}
388+
};
389+
390+
match next {
384391
b'0' => {
385392
// There can be only one leading '0'.
386393
match try!(self.peek_or_null()) {
@@ -496,7 +503,10 @@ impl<'de, R: Read<'de>> Deserializer<R> {
496503
}
497504

498505
if !at_least_one_digit {
499-
return Err(self.peek_error(ErrorCode::InvalidNumber));
506+
match try!(self.peek()) {
507+
Some(_) => return Err(self.peek_error(ErrorCode::InvalidNumber)),
508+
None => return Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
509+
}
500510
}
501511

502512
match try!(self.peek_or_null()) {
@@ -525,8 +535,15 @@ impl<'de, R: Read<'de>> Deserializer<R> {
525535
_ => true,
526536
};
527537

538+
let next = match try!(self.next_char()) {
539+
Some(b) => b,
540+
None => {
541+
return Err(self.error(ErrorCode::EofWhileParsingValue));
542+
}
543+
};
544+
528545
// Make sure a digit follows the exponent place.
529-
let mut exp = match try!(self.next_char_or_null()) {
546+
let mut exp = match next {
530547
c @ b'0'...b'9' => (c - b'0') as i32,
531548
_ => {
532549
return Err(self.error(ErrorCode::InvalidNumber));
@@ -623,19 +640,19 @@ impl<'de, R: Read<'de>> Deserializer<R> {
623640
}
624641

625642
#[cfg(feature = "arbitrary_precision")]
626-
fn scan_or_null(&mut self, buf: &mut String) -> Result<u8> {
643+
fn scan_or_eof(&mut self, buf: &mut String) -> Result<u8> {
627644
match try!(self.next_char()) {
628645
Some(b) => {
629646
buf.push(b as char);
630647
Ok(b)
631648
}
632-
None => Ok(b'\x00'),
649+
None => Err(self.error(ErrorCode::EofWhileParsingValue))
633650
}
634651
}
635652

636653
#[cfg(feature = "arbitrary_precision")]
637654
fn scan_integer(&mut self, buf: &mut String) -> Result<()> {
638-
match try!(self.scan_or_null(buf)) {
655+
match try!(self.scan_or_eof(buf)) {
639656
b'0' => {
640657
// There can be only one leading '0'.
641658
match try!(self.peek_or_null()) {
@@ -680,7 +697,10 @@ impl<'de, R: Read<'de>> Deserializer<R> {
680697
}
681698

682699
if !at_least_one_digit {
683-
return Err(self.peek_error(ErrorCode::InvalidNumber));
700+
match try!(self.peek()) {
701+
Some(_) => return Err(self.peek_error(ErrorCode::InvalidNumber)),
702+
None => return Err(self.peek_error(ErrorCode::EofWhileParsingValue)),
703+
}
684704
}
685705

686706
match try!(self.peek_or_null()) {
@@ -706,7 +726,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
706726
}
707727

708728
// Make sure a digit follows the exponent place.
709-
match try!(self.scan_or_null(buf)) {
729+
match try!(self.scan_or_eof(buf)) {
710730
b'0'...b'9' => {}
711731
_ => {
712732
return Err(self.error(ErrorCode::InvalidNumber));

tests/stream.rs

+30
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,36 @@ fn test_json_stream_truncated() {
8181
});
8282
}
8383

84+
#[test]
85+
fn test_json_stream_truncated_decimal() {
86+
let data = "{\"x\":4.";
87+
88+
test_stream!(data, Value, |stream| {
89+
assert!(stream.next().unwrap().unwrap_err().is_eof());
90+
assert_eq!(stream.byte_offset(), 0);
91+
});
92+
}
93+
94+
#[test]
95+
fn test_json_stream_truncated_negative() {
96+
let data = "{\"x\":-";
97+
98+
test_stream!(data, Value, |stream| {
99+
assert!(stream.next().unwrap().unwrap_err().is_eof());
100+
assert_eq!(stream.byte_offset(), 0);
101+
});
102+
}
103+
104+
#[test]
105+
fn test_json_stream_truncated_exponent() {
106+
let data = "{\"x\":4e";
107+
108+
test_stream!(data, Value, |stream| {
109+
assert!(stream.next().unwrap().unwrap_err().is_eof());
110+
assert_eq!(stream.byte_offset(), 0);
111+
});
112+
}
113+
84114
#[test]
85115
fn test_json_stream_empty() {
86116
let data = "";

tests/test.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -737,15 +737,15 @@ fn test_parse_number_errors() {
737737
test_parse_err::<f64>(&[
738738
("+", "expected value at line 1 column 1"),
739739
(".", "expected value at line 1 column 1"),
740-
("-", "invalid number at line 1 column 1"),
740+
("-", "EOF while parsing a value at line 1 column 1"),
741741
("00", "invalid number at line 1 column 2"),
742742
("0x80", "trailing characters at line 1 column 2"),
743743
("\\0", "expected value at line 1 column 1"),
744-
("1.", "invalid number at line 1 column 2"),
744+
("1.", "EOF while parsing a value at line 1 column 2"),
745745
("1.a", "invalid number at line 1 column 3"),
746746
("1.e1", "invalid number at line 1 column 3"),
747-
("1e", "invalid number at line 1 column 2"),
748-
("1e+", "invalid number at line 1 column 3"),
747+
("1e", "EOF while parsing a value at line 1 column 2"),
748+
("1e+", "EOF while parsing a value at line 1 column 3"),
749749
("1a", "trailing characters at line 1 column 2"),
750750
(
751751
"100e777777777777777777777777777",

0 commit comments

Comments
 (0)