Parser: Safe token queue, Rustify errors

This commit is contained in:
Simon Ask Ulsnes 2024-02-02 09:52:53 +01:00
parent 77716c3b53
commit 04168ca612
9 changed files with 583 additions and 699 deletions

View file

@ -14,9 +14,9 @@ description = "Safer libyaml port, based on unsafe-libyaml"
documentation = "https://docs.rs/libyaml-safer" documentation = "https://docs.rs/libyaml-safer"
edition = "2021" edition = "2021"
keywords = ["yaml"] keywords = ["yaml"]
license = "MIT" license = "Apache 2.0 OR MIT"
repository = "https://github.com/simonask/libyaml-safer" repository = "https://github.com/simonask/libyaml-safer"
rust-version = "1.56" rust-version = "1.70"
[workspace] [workspace]
[dev-dependencies] [dev-dependencies]
@ -26,6 +26,9 @@ unsafe-libyaml-test-suite = { path = "tests/data" }
[lib] [lib]
doc-scrape-examples = false doc-scrape-examples = false
[dependencies]
thiserror = "1.0"
[package.metadata.docs.rs] [package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"] targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"] rustdoc-args = ["--generate-link-to-definition"]

View file

@ -12,14 +12,12 @@
)] )]
use libyaml_safer::{ use libyaml_safer::{
yaml_event_delete, yaml_event_t, yaml_parser_delete, yaml_parser_initialize, yaml_parser_parse, yaml_parser_delete, yaml_parser_initialize, yaml_parser_parse, yaml_parser_set_input,
yaml_parser_set_input, yaml_parser_t, YamlEventData, YAML_DOUBLE_QUOTED_SCALAR_STYLE, yaml_parser_t, YamlEventData, YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FOLDED_SCALAR_STYLE,
YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_PLAIN_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE,
YAML_SINGLE_QUOTED_SCALAR_STYLE,
}; };
use std::env; use std::env;
use std::error::Error; use std::error::Error;
use std::fmt::Write as _;
use std::fs::File; use std::fs::File;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
@ -38,21 +36,15 @@ pub(crate) unsafe fn unsafe_main(
yaml_parser_set_input(&mut parser, stdin); yaml_parser_set_input(&mut parser, stdin);
let mut event = yaml_event_t::default();
loop { loop {
if yaml_parser_parse(&mut parser, &mut event).is_err() { let event = match yaml_parser_parse(&mut parser) {
let mut error = format!("Parse error: {}", parser.problem.unwrap_or("")); Err(err) => {
if parser.problem_mark.line != 0 || parser.problem_mark.column != 0 { let error = format!("Parse error: {}", err);
let _ = write!( yaml_parser_delete(&mut parser);
error, return Err(error.into());
"\nLine: {} Column: {}",
(parser.problem_mark.line).wrapping_add(1_u64),
(parser.problem_mark.column).wrapping_add(1_u64),
);
} }
yaml_parser_delete(&mut parser); Ok(event) => event,
return Err(error.into()); };
}
let mut is_end = false; let mut is_end = false;
@ -137,7 +129,6 @@ pub(crate) unsafe fn unsafe_main(
} }
} }
yaml_event_delete(&mut event);
if is_end { if is_end {
break; break;
} }

View file

@ -30,7 +30,7 @@ pub enum ReaderError {
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum ScannerError { pub enum ScannerError {
#[error("{problem}")] #[error("{}:{}: {} {} ({}:{})", problem_mark.line, problem_mark.column, problem, context, context_mark.line, context_mark.column)]
Problem { Problem {
context: &'static str, context: &'static str,
context_mark: yaml_mark_t, context_mark: yaml_mark_t,
@ -40,3 +40,41 @@ pub enum ScannerError {
#[error(transparent)] #[error(transparent)]
Reader(#[from] ReaderError), Reader(#[from] ReaderError),
} }
#[derive(Debug, thiserror::Error)]
pub enum ParserError {
#[error("no more tokens")]
UnexpectedEof,
#[error("{}:{}: {}", mark.line, mark.column, problem)]
Problem {
problem: &'static str,
mark: yaml_mark_t,
},
#[error("{}:{}: {} {} ({}:{})", mark.line, mark.column, problem, context, context_mark.line, context_mark.column)]
ProblemWithContext {
context: &'static str,
context_mark: yaml_mark_t,
problem: &'static str,
mark: yaml_mark_t,
},
#[error(transparent)]
Scanner(#[from] ScannerError),
}
#[derive(Debug, thiserror::Error)]
pub enum ComposerError {
#[error("{}:{}: {}", mark.line, mark.column, problem)]
Problem {
problem: &'static str,
mark: yaml_mark_t,
},
#[error("{}:{}: {} {} ({}:{})", mark.line, mark.column, problem, context, context_mark.line, context_mark.column)]
ProblemWithContext {
context: &'static str,
context_mark: yaml_mark_t,
problem: &'static str,
mark: yaml_mark_t,
},
#[error(transparent)]
Parser(#[from] ParserError),
}

View file

@ -169,9 +169,7 @@ tie-fighter: '|\-*-/|'
let mut read_in = SANITY_INPUT.as_bytes(); let mut read_in = SANITY_INPUT.as_bytes();
yaml_parser_set_input_string(&mut parser, &mut read_in); yaml_parser_set_input_string(&mut parser, &mut read_in);
let mut doc = yaml_document_t::default(); let mut doc = yaml_document_t::default();
if yaml_parser_load(&mut parser, &mut doc).is_err() { yaml_parser_load(&mut parser, &mut doc).unwrap();
panic!("parser error: {:?} {:?}", parser.error, parser.problem);
}
// let mut doc = doc.assume_init(); // let mut doc = doc.assume_init();
// let mut emitter = core::mem::MaybeUninit::uninit(); // let mut emitter = core::mem::MaybeUninit::uninit();
@ -196,6 +194,22 @@ tie-fighter: '|\-*-/|'
} }
} }
const TEST_CASE_QF4Y: &str = r#"[
foo: bar
]
"#;
#[test]
fn test_case() {
let mut parser = 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();
unsafe {
yaml_parser_load(&mut parser, &mut doc).unwrap();
}
}
// #[test] // #[test]
// fn integration_s7bg() { // fn integration_s7bg() {
// unsafe { // unsafe {
@ -288,4 +302,12 @@ tie-fighter: '|\-*-/|'
emitter.assume_init() 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

@ -4,8 +4,7 @@ use alloc::{vec, vec::Vec};
use crate::yaml::{YamlEventData, YamlNodeData}; use crate::yaml::{YamlEventData, YamlNodeData};
use crate::{ use crate::{
libc, yaml_alias_data_t, yaml_document_delete, yaml_document_t, yaml_event_t, yaml_mark_t, libc, yaml_alias_data_t, yaml_document_delete, yaml_document_t, yaml_event_t, yaml_mark_t,
yaml_node_pair_t, yaml_node_t, yaml_parser_parse, yaml_parser_t, YAML_COMPOSER_ERROR, yaml_node_pair_t, yaml_node_t, yaml_parser_parse, yaml_parser_t, ComposerError,
YAML_MEMORY_ERROR,
}; };
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
@ -26,65 +25,71 @@ use core::mem::MaybeUninit;
pub unsafe fn yaml_parser_load( pub unsafe fn yaml_parser_load(
parser: &mut yaml_parser_t, parser: &mut yaml_parser_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
let mut event = yaml_event_t::default();
*document = yaml_document_t::default(); *document = yaml_document_t::default();
document.nodes.reserve(16); document.nodes.reserve(16);
if !parser.stream_start_produced { if !parser.stream_start_produced {
if let Err(()) = yaml_parser_parse(parser, &mut event) { match yaml_parser_parse(parser) {
yaml_parser_delete_aliases(parser); Ok(yaml_event_t {
yaml_document_delete(document); data: YamlEventData::StreamStart { .. },
return Err(()); ..
} else { }) => (),
if let YamlEventData::StreamStart { .. } = &event.data { Ok(_) => panic!("expected stream start"),
} else { Err(err) => {
panic!("expected stream start"); yaml_parser_delete_aliases(parser);
yaml_document_delete(document);
return Err(err.into());
} }
} }
} }
if parser.stream_end_produced { if parser.stream_end_produced {
return Ok(()); return Ok(());
} }
if let Ok(()) = yaml_parser_parse(parser, &mut event) { let err: ComposerError;
if let YamlEventData::StreamEnd = &event.data { match yaml_parser_parse(parser) {
return Ok(()); Ok(event) => {
} if let YamlEventData::StreamEnd = &event.data {
parser.aliases.reserve(16); return Ok(());
if let Ok(()) = yaml_parser_load_document(parser, &mut event, document) { }
yaml_parser_delete_aliases(parser); parser.aliases.reserve(16);
return Ok(()); match yaml_parser_load_document(parser, event, document) {
Ok(()) => {
yaml_parser_delete_aliases(parser);
return Ok(());
}
Err(e) => err = e,
}
} }
Err(e) => err = e.into(),
} }
yaml_parser_delete_aliases(parser); yaml_parser_delete_aliases(parser);
yaml_document_delete(document); yaml_document_delete(document);
Err(()) Err(err)
} }
fn yaml_parser_set_composer_error( fn yaml_parser_set_composer_error<T>(
parser: &mut yaml_parser_t,
problem: &'static str, problem: &'static str,
problem_mark: yaml_mark_t, problem_mark: yaml_mark_t,
) -> Result<(), ()> { ) -> Result<T, ComposerError> {
parser.error = YAML_COMPOSER_ERROR; Err(ComposerError::Problem {
parser.problem = Some(problem); problem,
parser.problem_mark = problem_mark; mark: problem_mark,
Err(()) })
} }
fn yaml_parser_set_composer_error_context( fn yaml_parser_set_composer_error_context<T>(
parser: &mut yaml_parser_t,
context: &'static str, context: &'static str,
context_mark: yaml_mark_t, context_mark: yaml_mark_t,
problem: &'static str, problem: &'static str,
problem_mark: yaml_mark_t, problem_mark: yaml_mark_t,
) -> Result<(), ()> { ) -> Result<T, ComposerError> {
parser.error = YAML_COMPOSER_ERROR; Err(ComposerError::ProblemWithContext {
parser.context = Some(context); context,
parser.context_mark = context_mark; context_mark,
parser.problem = Some(problem); problem,
parser.problem_mark = problem_mark; mark: problem_mark,
Err(()) })
} }
unsafe fn yaml_parser_delete_aliases(parser: &mut yaml_parser_t) { unsafe fn yaml_parser_delete_aliases(parser: &mut yaml_parser_t) {
@ -93,24 +98,24 @@ unsafe fn yaml_parser_delete_aliases(parser: &mut yaml_parser_t) {
unsafe fn yaml_parser_load_document( unsafe fn yaml_parser_load_document(
parser: &mut yaml_parser_t, parser: &mut yaml_parser_t,
event: &mut yaml_event_t, event: yaml_event_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
let mut ctx = vec![]; let mut ctx = vec![];
if let YamlEventData::DocumentStart { if let YamlEventData::DocumentStart {
version_directive, version_directive,
tag_directives, tag_directives,
implicit, implicit,
} = &mut event.data } = event.data
{ {
document.version_directive = *version_directive; document.version_directive = version_directive;
document.tag_directives = core::mem::take(tag_directives); document.tag_directives = tag_directives;
document.start_implicit = *implicit; document.start_implicit = implicit;
document.start_mark = event.start_mark; document.start_mark = event.start_mark;
ctx.reserve(16); ctx.reserve(16);
if let Err(()) = yaml_parser_load_nodes(parser, document, &mut ctx) { if let Err(err) = yaml_parser_load_nodes(parser, document, &mut ctx) {
ctx.clear(); ctx.clear();
return Err(()); return Err(err);
} }
ctx.clear(); ctx.clear();
Ok(()) Ok(())
@ -123,40 +128,39 @@ unsafe fn yaml_parser_load_nodes(
parser: &mut yaml_parser_t, parser: &mut yaml_parser_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
ctx: &mut Vec<libc::c_int>, ctx: &mut Vec<libc::c_int>,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
let mut event = yaml_event_t::default();
let end_implicit; let end_implicit;
let end_mark; let end_mark;
loop { loop {
yaml_parser_parse(parser, &mut event)?; let event = yaml_parser_parse(parser)?;
match &event.data { match event.data {
YamlEventData::NoEvent => panic!("empty event"), YamlEventData::NoEvent => panic!("empty event"),
YamlEventData::StreamStart { .. } => panic!("unexpected stream start event"), YamlEventData::StreamStart { .. } => panic!("unexpected stream start event"),
YamlEventData::StreamEnd => panic!("unexpected stream end event"), YamlEventData::StreamEnd => panic!("unexpected stream end event"),
YamlEventData::DocumentStart { .. } => panic!("unexpected document start event"), YamlEventData::DocumentStart { .. } => panic!("unexpected document start event"),
YamlEventData::DocumentEnd { implicit } => { YamlEventData::DocumentEnd { implicit } => {
end_implicit = *implicit; end_implicit = implicit;
end_mark = event.end_mark; end_mark = event.end_mark;
break; break;
} }
YamlEventData::Alias { .. } => { YamlEventData::Alias { .. } => {
yaml_parser_load_alias(parser, &mut event, document, ctx)?; yaml_parser_load_alias(parser, event, document, ctx)?;
} }
YamlEventData::Scalar { .. } => { YamlEventData::Scalar { .. } => {
yaml_parser_load_scalar(parser, &mut event, document, ctx)?; yaml_parser_load_scalar(parser, event, document, ctx)?;
} }
YamlEventData::SequenceStart { .. } => { YamlEventData::SequenceStart { .. } => {
yaml_parser_load_sequence(parser, &mut event, document, ctx)?; yaml_parser_load_sequence(parser, event, document, ctx)?;
} }
YamlEventData::SequenceEnd => { YamlEventData::SequenceEnd => {
yaml_parser_load_sequence_end(parser, &mut event, document, ctx)?; yaml_parser_load_sequence_end(parser, event, document, ctx)?;
} }
YamlEventData::MappingStart { .. } => { YamlEventData::MappingStart { .. } => {
yaml_parser_load_mapping(parser, &mut event, document, ctx)?; yaml_parser_load_mapping(parser, event, document, ctx)?;
} }
YamlEventData::MappingEnd => { YamlEventData::MappingEnd => {
yaml_parser_load_mapping_end(parser, &mut event, document, ctx)?; yaml_parser_load_mapping_end(parser, event, document, ctx)?;
} }
} }
} }
@ -170,7 +174,7 @@ unsafe fn yaml_parser_register_anchor(
document: &mut yaml_document_t, document: &mut yaml_document_t,
index: libc::c_int, index: libc::c_int,
anchor: Option<String>, anchor: Option<String>,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
let Some(anchor) = anchor else { let Some(anchor) = anchor else {
return Ok(()); return Ok(());
}; };
@ -182,7 +186,6 @@ unsafe fn yaml_parser_register_anchor(
for alias_data in parser.aliases.iter() { for alias_data in parser.aliases.iter() {
if alias_data.anchor == data.anchor { if alias_data.anchor == data.anchor {
return yaml_parser_set_composer_error_context( return yaml_parser_set_composer_error_context(
parser,
"found duplicate anchor; first occurrence", "found duplicate anchor; first occurrence",
alias_data.mark, alias_data.mark,
"second occurrence", "second occurrence",
@ -195,11 +198,10 @@ unsafe fn yaml_parser_register_anchor(
} }
unsafe fn yaml_parser_load_node_add( unsafe fn yaml_parser_load_node_add(
parser: &mut yaml_parser_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
ctx: &mut Vec<libc::c_int>, ctx: &mut Vec<libc::c_int>,
index: libc::c_int, index: libc::c_int,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
if ctx.is_empty() { if ctx.is_empty() {
return Ok(()); return Ok(());
} }
@ -207,7 +209,6 @@ unsafe fn yaml_parser_load_node_add(
let parent = &mut document.nodes[parent_index as usize - 1]; let parent = &mut document.nodes[parent_index as usize - 1];
match parent.data { match parent.data {
YamlNodeData::Sequence { ref mut items, .. } => { YamlNodeData::Sequence { ref mut items, .. } => {
STACK_LIMIT!(parser, items)?;
items.push(index); items.push(index);
} }
YamlNodeData::Mapping { ref mut pairs, .. } => { YamlNodeData::Mapping { ref mut pairs, .. } => {
@ -224,7 +225,6 @@ unsafe fn yaml_parser_load_node_add(
if do_push { if do_push {
(*pair).key = index; (*pair).key = index;
(*pair).value = 0; (*pair).value = 0;
STACK_LIMIT!(parser, pairs)?;
pairs.push(*pair); pairs.push(*pair);
} }
} }
@ -237,10 +237,10 @@ unsafe fn yaml_parser_load_node_add(
unsafe fn yaml_parser_load_alias( unsafe fn yaml_parser_load_alias(
parser: &mut yaml_parser_t, parser: &mut yaml_parser_t,
event: &mut yaml_event_t, // TODO: Take by value event: yaml_event_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
ctx: &mut Vec<libc::c_int>, ctx: &mut Vec<libc::c_int>,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
let anchor: &str = if let YamlEventData::Alias { anchor } = &event.data { let anchor: &str = if let YamlEventData::Alias { anchor } = &event.data {
&*anchor &*anchor
} else { } else {
@ -249,72 +249,64 @@ unsafe fn yaml_parser_load_alias(
for alias_data in parser.aliases.iter() { for alias_data in parser.aliases.iter() {
if alias_data.anchor == anchor { if alias_data.anchor == anchor {
return yaml_parser_load_node_add(parser, document, ctx, alias_data.index); return yaml_parser_load_node_add(document, ctx, alias_data.index);
} }
} }
yaml_parser_set_composer_error(parser, "found undefined alias", event.start_mark) yaml_parser_set_composer_error("found undefined alias", event.start_mark)
} }
unsafe fn yaml_parser_load_scalar( unsafe fn yaml_parser_load_scalar(
parser: &mut yaml_parser_t, parser: &mut yaml_parser_t,
event: &mut yaml_event_t, // TODO: Take by value event: yaml_event_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
ctx: &mut Vec<libc::c_int>, ctx: &mut Vec<libc::c_int>,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
let (mut tag, value, style, anchor) = if let YamlEventData::Scalar { let YamlEventData::Scalar {
tag, mut tag,
value, value,
style, style,
anchor, anchor,
.. ..
} = &event.data } = event.data
{ else {
(tag.clone(), value, *style, anchor.clone())
} else {
unreachable!() unreachable!()
}; };
let index: libc::c_int; let index: libc::c_int;
if let Ok(()) = STACK_LIMIT!(parser, document.nodes) { if tag.is_none() || tag.as_deref() == Some("!") {
if tag.is_none() || tag.as_deref() == Some("!") { tag = Some(String::from("tag:yaml.org,2002:str"));
tag = Some(String::from("tag:yaml.org,2002:str"));
}
let node = yaml_node_t {
data: YamlNodeData::Scalar {
value: value.clone(), // TODO: move
style,
},
tag,
start_mark: (*event).start_mark,
end_mark: (*event).end_mark,
};
document.nodes.push(node);
index = document.nodes.len() as libc::c_int;
yaml_parser_register_anchor(parser, document, index, anchor)?;
return yaml_parser_load_node_add(parser, document, ctx, index);
} }
Err(()) let node = yaml_node_t {
data: YamlNodeData::Scalar { value, style },
tag,
start_mark: event.start_mark,
end_mark: event.end_mark,
};
document.nodes.push(node);
index = document.nodes.len() as libc::c_int;
yaml_parser_register_anchor(parser, document, index, anchor)?;
yaml_parser_load_node_add(document, ctx, index)
} }
unsafe fn yaml_parser_load_sequence( unsafe fn yaml_parser_load_sequence(
parser: &mut yaml_parser_t, parser: &mut yaml_parser_t,
event: &mut yaml_event_t, // TODO: Take by value. event: yaml_event_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
ctx: &mut Vec<libc::c_int>, ctx: &mut Vec<libc::c_int>,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
let (mut tag, style, anchor) = if let YamlEventData::SequenceStart { let YamlEventData::SequenceStart {
anchor, tag, style, .. anchor,
} = &event.data mut tag,
{ style,
(tag.clone(), *style, anchor) ..
} else { } = event.data
else {
unreachable!() unreachable!()
}; };
let mut items = Vec::with_capacity(16); let mut items = Vec::with_capacity(16);
let index: libc::c_int; let index: libc::c_int;
STACK_LIMIT!(parser, document.nodes)?;
if tag.is_none() || tag.as_deref() == Some("!") { if tag.is_none() || tag.as_deref() == Some("!") {
tag = Some(String::from("tag:yaml.org,2002:seq")); tag = Some(String::from("tag:yaml.org,2002:seq"));
} }
@ -332,47 +324,46 @@ unsafe fn yaml_parser_load_sequence(
document.nodes.push(node); document.nodes.push(node);
index = document.nodes.len() as libc::c_int; index = document.nodes.len() as libc::c_int;
yaml_parser_register_anchor(parser, document, index, anchor.clone())?; yaml_parser_register_anchor(parser, document, index, anchor.clone())?;
yaml_parser_load_node_add(parser, document, ctx, index)?; yaml_parser_load_node_add(document, ctx, index)?;
STACK_LIMIT!(parser, *ctx)?;
ctx.push(index); ctx.push(index);
Ok(()) Ok(())
} }
unsafe fn yaml_parser_load_sequence_end( unsafe fn yaml_parser_load_sequence_end(
_parser: &mut yaml_parser_t, _parser: &mut yaml_parser_t,
event: *mut yaml_event_t, event: yaml_event_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
ctx: &mut Vec<libc::c_int>, ctx: &mut Vec<libc::c_int>,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
__assert!(!ctx.is_empty()); __assert!(!ctx.is_empty());
let index: libc::c_int = *ctx.last().unwrap(); let index: libc::c_int = *ctx.last().unwrap();
__assert!(matches!( __assert!(matches!(
document.nodes[index as usize - 1].data, document.nodes[index as usize - 1].data,
YamlNodeData::Sequence { .. } YamlNodeData::Sequence { .. }
)); ));
document.nodes[index as usize - 1].end_mark = (*event).end_mark; document.nodes[index as usize - 1].end_mark = event.end_mark;
_ = ctx.pop(); _ = ctx.pop();
Ok(()) Ok(())
} }
unsafe fn yaml_parser_load_mapping( unsafe fn yaml_parser_load_mapping(
parser: &mut yaml_parser_t, parser: &mut yaml_parser_t,
event: &mut yaml_event_t, // TODO: take by value event: yaml_event_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
ctx: &mut Vec<libc::c_int>, ctx: &mut Vec<libc::c_int>,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
let (mut tag, style, anchor) = if let YamlEventData::MappingStart { let YamlEventData::MappingStart {
anchor, tag, style, .. anchor,
} = &event.data mut tag,
{ style,
(tag.clone(), *style, anchor.clone()) ..
} else { } = event.data
else {
unreachable!() unreachable!()
}; };
let mut pairs = Vec::with_capacity(16); let mut pairs = Vec::with_capacity(16);
let index: libc::c_int; let index: libc::c_int;
STACK_LIMIT!(parser, document.nodes)?;
if tag.is_none() || tag.as_deref() == Some("!") { if tag.is_none() || tag.as_deref() == Some("!") {
tag = Some(String::from("tag:yaml.org,2002:map")); tag = Some(String::from("tag:yaml.org,2002:map"));
} }
@ -388,25 +379,24 @@ unsafe fn yaml_parser_load_mapping(
document.nodes.push(node); document.nodes.push(node);
index = document.nodes.len() as libc::c_int; index = document.nodes.len() as libc::c_int;
yaml_parser_register_anchor(parser, document, index, anchor)?; yaml_parser_register_anchor(parser, document, index, anchor)?;
yaml_parser_load_node_add(parser, document, ctx, index)?; yaml_parser_load_node_add(document, ctx, index)?;
STACK_LIMIT!(parser, *ctx)?;
ctx.push(index); ctx.push(index);
Ok(()) Ok(())
} }
unsafe fn yaml_parser_load_mapping_end( unsafe fn yaml_parser_load_mapping_end(
_parser: &mut yaml_parser_t, _parser: &mut yaml_parser_t,
event: *mut yaml_event_t, event: yaml_event_t,
document: &mut yaml_document_t, document: &mut yaml_document_t,
ctx: &mut Vec<libc::c_int>, ctx: &mut Vec<libc::c_int>,
) -> Result<(), ()> { ) -> Result<(), ComposerError> {
__assert!(!ctx.is_empty()); __assert!(!ctx.is_empty());
let index: libc::c_int = *ctx.last().unwrap(); let index: libc::c_int = *ctx.last().unwrap();
__assert!(matches!( __assert!(matches!(
document.nodes[index as usize - 1].data, document.nodes[index as usize - 1].data,
YamlNodeData::Mapping { .. } YamlNodeData::Mapping { .. }
)); ));
document.nodes[index as usize - 1].end_mark = (*event).end_mark; document.nodes[index as usize - 1].end_mark = event.end_mark;
_ = ctx.pop(); _ = ctx.pop();
Ok(()) Ok(())
} }

View file

@ -268,17 +268,6 @@ macro_rules! IS_BLANKZ {
}; };
} }
macro_rules! STACK_LIMIT {
($context:expr, $stack:expr) => {
if $stack.len() < libc::c_int::MAX as usize - 1 {
Ok(())
} else {
(*$context).error = YAML_MEMORY_ERROR;
Err(())
}
};
}
pub(crate) fn vecdeque_starts_with<T: PartialEq + Copy>( pub(crate) fn vecdeque_starts_with<T: PartialEq + Copy>(
vec: &alloc::collections::VecDeque<T>, vec: &alloc::collections::VecDeque<T>,
needle: &[T], needle: &[T],

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ use crate::yaml::{ptrdiff_t, size_t, YamlTokenData};
use crate::{ use crate::{
libc, yaml_mark_t, yaml_parser_t, yaml_simple_key_t, yaml_token_t, ReaderError, ScannerError, libc, yaml_mark_t, yaml_parser_t, yaml_simple_key_t, yaml_token_t, ReaderError, ScannerError,
YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE, YAML_DOUBLE_QUOTED_SCALAR_STYLE, YAML_FOLDED_SCALAR_STYLE, YAML_LITERAL_SCALAR_STYLE,
YAML_NO_ERROR, YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE, YAML_PLAIN_SCALAR_STYLE, YAML_SINGLE_QUOTED_SCALAR_STYLE,
}; };
fn CACHE(parser: &mut yaml_parser_t, length: size_t) -> Result<(), ReaderError> { fn CACHE(parser: &mut yaml_parser_t, length: size_t) -> Result<(), ReaderError> {
@ -99,28 +99,25 @@ fn READ_LINE_STRING(parser: &mut yaml_parser_t, string: &mut String) {
/// An application must not alternate the calls of yaml_parser_scan() with the /// An application must not alternate the calls of yaml_parser_scan() with the
/// calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break /// calls of yaml_parser_parse() or yaml_parser_load(). Doing this will break
/// the parser. /// the parser.
pub fn yaml_parser_scan( pub fn yaml_parser_scan(parser: &mut yaml_parser_t) -> Result<yaml_token_t, ScannerError> {
parser: &mut yaml_parser_t, if parser.stream_end_produced {
token: &mut yaml_token_t, return Ok(yaml_token_t {
) -> Result<(), ScannerError> { data: YamlTokenData::StreamEnd,
*token = yaml_token_t::default(); ..Default::default()
if parser.stream_end_produced || parser.error != YAML_NO_ERROR { });
return Ok(());
} }
if !parser.token_available { if !parser.token_available {
yaml_parser_fetch_more_tokens(parser)?; yaml_parser_fetch_more_tokens(parser)?;
} }
if let Some(popped) = parser.tokens.pop_front() { if let Some(token) = parser.tokens.pop_front() {
*token = popped;
parser.token_available = false; parser.token_available = false;
parser.tokens_parsed = parser.tokens_parsed.force_add(1); parser.tokens_parsed = parser.tokens_parsed.force_add(1);
if let YamlTokenData::StreamEnd = &(*token).data { if let YamlTokenData::StreamEnd = &token.data {
parser.stream_end_produced = true; parser.stream_end_produced = true;
} }
Ok(()) Ok(token)
} else { } else {
// token_available should have been false unreachable!("no more tokens, but stream-end was not produced")
unreachable!()
} }
} }

View file

@ -670,20 +670,6 @@ pub struct yaml_alias_data_t {
#[repr(C)] #[repr(C)]
#[non_exhaustive] #[non_exhaustive]
pub struct yaml_parser_t<'r> { pub struct yaml_parser_t<'r> {
/// Error type.
pub error: yaml_error_type_t,
/// Error description.
pub problem: Option<&'static str>,
/// The byte about which the problem occured.
pub problem_offset: size_t,
/// The problematic value (-1 is none).
pub problem_value: libc::c_int,
/// The problem position.
pub problem_mark: yaml_mark_t,
/// The error context.
pub context: Option<&'static str>,
/// The context position.
pub context_mark: yaml_mark_t,
/// Read handler. /// Read handler.
pub(crate) read_handler: Option<&'r mut dyn std::io::Read>, pub(crate) read_handler: Option<&'r mut dyn std::io::Read>,
/// Standard (string or file) input data. /// Standard (string or file) input data.
@ -743,13 +729,6 @@ pub struct yaml_parser_t<'r> {
impl<'r> Default for yaml_parser_t<'r> { impl<'r> Default for yaml_parser_t<'r> {
fn default() -> Self { fn default() -> Self {
Self { Self {
error: Default::default(),
problem: Default::default(),
problem_offset: Default::default(),
problem_value: Default::default(),
problem_mark: Default::default(),
context: Default::default(),
context_mark: Default::default(),
read_handler: None, read_handler: None,
input: Default::default(), input: Default::default(),
eof: Default::default(), eof: Default::default(),