Replace yaml_parser_initialize with safe alternative

This commit is contained in:
Simon Ask Ulsnes 2024-02-02 10:05:15 +01:00
parent 47351cfe7c
commit 4a863e1f78
4 changed files with 43 additions and 68 deletions

View file

@ -4,11 +4,12 @@ use alloc::vec::Vec;
use crate::yaml::{YamlEventData, YamlNodeData};
use crate::{
libc, yaml_break_t, yaml_document_t, yaml_emitter_t, yaml_encoding_t, yaml_event_t,
yaml_mapping_style_t, yaml_mark_t, yaml_node_pair_t, yaml_node_t, yaml_parser_t,
yaml_scalar_style_t, yaml_sequence_style_t, yaml_tag_directive_t, yaml_token_t,
yaml_mapping_style_t, yaml_mark_t, yaml_node_pair_t, yaml_node_t, yaml_parser_state_t,
yaml_parser_t, yaml_scalar_style_t, yaml_sequence_style_t, yaml_tag_directive_t, yaml_token_t,
yaml_version_directive_t, YAML_ANY_ENCODING, YAML_UTF8_ENCODING,
};
use core::ptr;
use std::collections::VecDeque;
pub(crate) const INPUT_RAW_BUFFER_SIZE: usize = 16384;
pub(crate) const INPUT_BUFFER_SIZE: usize = INPUT_RAW_BUFFER_SIZE;
@ -18,19 +19,33 @@ pub(crate) const OUTPUT_BUFFER_SIZE: usize = 16384;
///
/// This function creates a new parser object. An application is responsible
/// for destroying the object using the yaml_parser_delete() function.
pub unsafe fn yaml_parser_initialize(parser: *mut yaml_parser_t) -> Result<(), ()> {
__assert!(!parser.is_null());
core::ptr::write(parser, yaml_parser_t::default());
let parser = &mut *parser;
parser.raw_buffer.reserve(INPUT_RAW_BUFFER_SIZE);
parser.buffer.reserve(INPUT_BUFFER_SIZE);
parser.tokens.reserve(16);
parser.indents.reserve(16);
parser.simple_keys.reserve(16);
parser.states.reserve(16);
parser.marks.reserve(16);
parser.tag_directives.reserve(16);
Ok(())
pub fn yaml_parser_new<'r>() -> yaml_parser_t<'r> {
yaml_parser_t {
read_handler: None,
input: Default::default(),
eof: false,
buffer: VecDeque::with_capacity(INPUT_BUFFER_SIZE),
unread: 0,
raw_buffer: VecDeque::with_capacity(INPUT_RAW_BUFFER_SIZE),
encoding: YAML_ANY_ENCODING,
offset: 0,
mark: yaml_mark_t::default(),
stream_start_produced: false,
stream_end_produced: false,
flow_level: 0,
tokens: VecDeque::with_capacity(16),
tokens_parsed: 0,
token_available: false,
indents: Vec::with_capacity(16),
indent: 0,
simple_key_allowed: false,
simple_keys: Vec::with_capacity(16),
states: Vec::with_capacity(16),
state: yaml_parser_state_t::default(),
marks: Vec::with_capacity(16),
tag_directives: Vec::with_capacity(16),
aliases: Vec::new(),
}
}
/// Destroy a parser.

View file

@ -12,27 +12,22 @@
)]
use libyaml_safer::{
yaml_parser_delete, yaml_parser_initialize, yaml_parser_parse, yaml_parser_set_input,
yaml_parser_t, YamlEventData, YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FOLDED_SCALAR_STYLE,
YAML_LITERAL_SCALAR_STYLE, YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE,
yaml_parser_delete, yaml_parser_new, yaml_parser_parse, yaml_parser_set_input, YamlEventData,
YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE,
YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE,
};
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::{self, Read, Write};
use std::mem::MaybeUninit;
use std::process::{self, ExitCode};
use std::slice;
pub(crate) unsafe fn unsafe_main(
pub(crate) fn test_main(
stdin: &mut dyn Read,
stdout: &mut dyn Write,
) -> Result<(), Box<dyn Error>> {
let mut parser = MaybeUninit::<yaml_parser_t>::uninit();
if yaml_parser_initialize(parser.as_mut_ptr()).is_err() {
return Err("Could not initialize the parser object".into());
}
let mut parser = parser.assume_init();
let mut parser = yaml_parser_new();
yaml_parser_set_input(&mut parser, stdin);
@ -137,7 +132,7 @@ pub(crate) unsafe fn unsafe_main(
Ok(())
}
unsafe fn print_escaped(stdout: &mut dyn Write, s: &str) {
fn print_escaped(stdout: &mut dyn Write, s: &str) {
for ch in s.bytes() {
let repr = match &ch {
b'\\' => b"\\\\",
@ -161,7 +156,7 @@ fn main() -> ExitCode {
for arg in args {
let mut stdin = File::open(arg).unwrap();
let mut stdout = io::stdout();
let result = unsafe { unsafe_main(&mut stdin, &mut stdout) };
let result = test_main(&mut stdin, &mut stdout);
if let Err(err) = result {
let _ = writeln!(io::stderr(), "{}", err);
return ExitCode::FAILURE;

View file

@ -116,8 +116,8 @@ pub use crate::api::{
yaml_emitter_set_indent, yaml_emitter_set_output, yaml_emitter_set_output_string,
yaml_emitter_set_unicode, yaml_emitter_set_width, yaml_event_delete,
yaml_mapping_end_event_initialize, yaml_mapping_start_event_initialize, yaml_parser_delete,
yaml_parser_initialize, yaml_parser_set_encoding, yaml_parser_set_input,
yaml_parser_set_input_string, yaml_scalar_event_initialize, yaml_sequence_end_event_initialize,
yaml_parser_new, yaml_parser_set_encoding, yaml_parser_set_input, yaml_parser_set_input_string,
yaml_scalar_event_initialize, yaml_sequence_end_event_initialize,
yaml_sequence_start_event_initialize, yaml_stream_end_event_initialize,
yaml_stream_start_event_initialize, yaml_token_delete,
};
@ -150,9 +150,7 @@ mod tests {
#[test]
fn sanity() {
unsafe {
let mut parser = core::mem::MaybeUninit::uninit();
yaml_parser_initialize(parser.as_mut_ptr()).unwrap();
let mut parser = parser.assume_init();
let mut parser = yaml_parser_new();
// const SANITY_INPUT: &'static str =
// "Mark McGwire:\n hr: 65\n avg: 0.278\nSammy Sosa:\n hr: 63\n avg: 0.288\n";
const SANITY_INPUT: &'static str = r#"
@ -199,7 +197,7 @@ foo: bar
#[test]
fn test_case() {
let mut parser = parser_new();
let mut parser = yaml_parser_new();
let mut input = TEST_CASE_QF4Y.as_bytes();
yaml_parser_set_input_string(&mut parser, &mut input);
let mut doc = yaml_document_t::default();
@ -298,12 +296,4 @@ foo: bar
emitter.assume_init()
}
}
fn parser_new<'w>() -> yaml_parser_t<'w> {
unsafe {
let mut emitter = core::mem::MaybeUninit::uninit();
yaml_parser_initialize(emitter.as_mut_ptr()).unwrap();
emitter.assume_init()
}
}
}

View file

@ -2,7 +2,7 @@ use alloc::collections::VecDeque;
use alloc::string::String;
use alloc::vec::Vec;
use crate::libc;
use crate::{api::yaml_parser_new, libc};
use core::ptr;
pub use self::yaml_encoding_t::*;
@ -688,32 +688,7 @@ pub struct yaml_parser_t<'r> {
impl<'r> Default for yaml_parser_t<'r> {
fn default() -> Self {
Self {
read_handler: None,
input: Default::default(),
eof: Default::default(),
buffer: Default::default(),
unread: Default::default(),
raw_buffer: Default::default(),
encoding: Default::default(),
offset: Default::default(),
mark: Default::default(),
stream_start_produced: Default::default(),
stream_end_produced: Default::default(),
flow_level: Default::default(),
tokens: Default::default(),
tokens_parsed: Default::default(),
token_available: Default::default(),
indents: Default::default(),
indent: Default::default(),
simple_key_allowed: Default::default(),
simple_keys: Default::default(),
states: Default::default(),
state: Default::default(),
marks: Default::default(),
tag_directives: Default::default(),
aliases: Default::default(),
}
yaml_parser_new()
}
}