1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Test for InputBufferFull error variant
use picojson::{ParseError, PullParser, StreamParser};
use std::io;
/// Mock reader that simulates a scenario where input buffer limits could be exceeded
struct LargeDataReader {
data: Vec<u8>,
position: usize,
chunk_size: usize,
}
impl LargeDataReader {
fn new(json_data: &str, chunk_size: usize) -> Self {
Self {
data: json_data.as_bytes().to_vec(),
position: 0,
chunk_size,
}
}
}
impl picojson::Reader for LargeDataReader {
type Error = io::Error;
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if self.position >= self.data.len() {
return Ok(0); // End of stream
}
let remaining = self.data.len() - self.position;
let to_read = std::cmp::min(std::cmp::min(buf.len(), self.chunk_size), remaining);
buf[..to_read].copy_from_slice(&self.data[self.position..self.position + to_read]);
self.position += to_read;
Ok(to_read)
}
}
#[test]
fn test_input_buffer_full_scenario() {
// Create a very large JSON document that could potentially overflow input buffers
let large_object = format!(
r#"{{"key": "{}"}}"#,
"x".repeat(10000) // Very long string value
);
// Use a very small buffer that would be insufficient for the large content
let mut buffer = [0u8; 32]; // Intentionally small buffer
let reader = LargeDataReader::new(&large_object, 16); // Small read chunks
let mut parser = StreamParser::new(reader, &mut buffer);
// Attempt to parse the large document with insufficient buffer space
let mut events = Vec::new();
loop {
match parser.next_event() {
Ok(event) => {
events.push(format!("{:?}", event));
if matches!(event, picojson::Event::EndDocument) {
break;
}
}
Err(e) => {
// InputBufferFull is now properly implemented as of stream_content_builder.rs fix
if matches!(
e,
ParseError::InputBufferFull | ParseError::ScratchBufferFull
) {
// This is an expected error for oversized tokens.
return;
}
panic!("Unexpected error: {:?}", e);
}
}
}
// If we reach here, the parser somehow managed to handle the large document
// This is unexpected behavior that should cause the test to fail
panic!(
"Test should have failed: Parser unexpectedly succeeded in handling large document with small buffer. \
Expected ScratchBufferFull or InputBufferFull error, but got {} events: {:?}",
events.len(),
events
);
}
#[test]
fn test_input_buffer_full_with_extremely_long_token() {
// Test with an extremely long single token that exceeds reasonable input buffer limits
let extremely_long_key = "k".repeat(50000);
let json = format!(r#"{{"{key}": "value"}}"#, key = extremely_long_key);
let mut buffer = [0u8; 64]; // Very small buffer
let reader = LargeDataReader::new(&json, 32);
let mut parser = StreamParser::new(reader, &mut buffer);
match parser.next_event() {
Ok(_) => {
// Continue parsing to see what happens
loop {
match parser.next_event() {
Ok(event) => {
if matches!(event, picojson::Event::EndDocument) {
break;
}
}
Err(e) => {
if matches!(
e,
ParseError::InputBufferFull | ParseError::ScratchBufferFull
) {
// This is an expected error for extremely long tokens.
return;
}
panic!("Unexpected error for extremely long token: {:?}", e);
}
}
}
}
Err(e) => {
match e {
ParseError::ScratchBufferFull | ParseError::InputBufferFull => {
// This is an expected error for extremely long tokens.
}
_ => {
panic!(
"Unexpected error on first event for extremely long token: {:?}",
e
);
}
}
}
}
}