Skip to content
This repository has been archived by the owner on Jan 29, 2023. It is now read-only.

Commit

Permalink
🐛 fix issue when including a file that has an array concatenation wit…
Browse files Browse the repository at this point in the history
…h a substitution #26

alsoo fix case for stack overflow when substituting a value that hasn't been defined in some cases
  • Loading branch information
mockersf committed Aug 25, 2020
1 parent 3621b83 commit fc0aa01
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 63 deletions.
137 changes: 101 additions & 36 deletions src/internals/intermediate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,40 @@ pub(crate) enum Node {
},
}

const STATIC_TRUE: bool = true;
const STATIC_FALSE: bool = false;
impl Child {
fn is_array_leaf_included(&self) -> bool {
*std::cell::Ref::map(self.value.borrow(), |v| {
if let Node::Node { children, .. } = v {
let is_included_leaf = children
.get(0)
.map(|child| {
*std::cell::Ref::map(child.value.borrow(), |v| {
if let Node::Leaf(l) = v {
if let HoconValue::Included { .. } = l {
&true
} else {
&false
}
} else {
&false
}
})
})
.unwrap_or(false);
if is_included_leaf {
&STATIC_TRUE
} else {
&STATIC_FALSE
}
} else {
&STATIC_FALSE
}
})
}
}

impl Node {
pub(crate) fn deep_clone(&self) -> Self {
match self {
Expand All @@ -39,52 +73,83 @@ impl Node {
root: &HoconIntermediate,
config: &HoconLoaderConfig,
included_path: Option<Vec<HoconValue>>,
substituting_path: Option<Vec<HoconValue>>,
) -> Result<Hocon, crate::Error> {
match self {
Node::Leaf(v) => v.finalize(root, config, false, included_path),
Node::Leaf(v) => v.finalize(root, config, false, included_path, substituting_path),
Node::Node {
ref children,
ref key_hint,
} => children
.first()
.map(|ref first| match first.key {
HoconValue::Integer(_) | HoconValue::Null(_) => {
Ok(Hocon::Array(crate::helper::extract_result(
children
.iter()
.map(|c| {
c.value.clone().into_inner().finalize(
root,
config,
included_path.clone(),
)
})
.collect(),
)?))
}
HoconValue::String(_) => Ok(Hocon::Hash(
crate::helper::extract_result(
children
.iter()
.map(|c| {
(
c.key.clone().string_value(),
.map(
|ref first| match (&first.key, &first.is_array_leaf_included()) {
(HoconValue::Null(_), true) => Ok(Hocon::Array(
crate::helper::extract_result(
children
.iter()
.map(|c| {
c.value.clone().into_inner().finalize(
root,
config,
included_path.clone(),
),
)
})
.map(|(k, v)| v.map(|v| (k, v)))
.collect(),
)?
.into_iter()
.collect(),
)),
// Keys should only be integer or strings
_ => unreachable!(),
})
substituting_path.clone(),
)
})
.collect(),
)?
.into_iter()
.map(|v| {
if let Hocon::Array(vs) = v {
vs.into_iter()
} else {
vec![v].into_iter()
}
})
.flatten()
.collect(),
)),
(HoconValue::Integer(_), _) | (HoconValue::Null(_), _) => {
Ok(Hocon::Array(crate::helper::extract_result(
children
.iter()
.map(|c| {
c.value.clone().into_inner().finalize(
root,
config,
included_path.clone(),
substituting_path.clone(),
)
})
.collect(),
)?))
}

(HoconValue::String(_), _) => Ok(Hocon::Hash(
crate::helper::extract_result(
children
.iter()
.map(|c| {
(
c.key.clone().string_value(),
c.value.clone().into_inner().finalize(
root,
config,
included_path.clone(),
substituting_path.clone(),
),
)
})
.map(|(k, v)| v.map(|v| (k, v)))
.collect(),
)?
.into_iter()
.collect(),
)),
// Keys should only be integer or strings
_ => unreachable!(),
},
)
.unwrap_or_else(|| match key_hint {
Some(KeyType::Int) => Ok(Hocon::Array(vec![])),
Some(KeyType::String) | None => Ok(Hocon::Hash(HashMap::new())),
Expand Down Expand Up @@ -172,6 +237,6 @@ impl HoconIntermediate {
#[allow(clippy::redundant_clone)]
// looks like https://github.com/rust-lang/rust-clippy/issues/5707
let refself = &self.clone();
self.tree.finalize(refself, config, None)
self.tree.finalize(refself, config, None, None)
}
}
72 changes: 45 additions & 27 deletions src/internals/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl HoconValue {
config: &HoconLoaderConfig,
in_concat: bool,
included_path: Option<Vec<HoconValue>>,
substituting_path: Option<Vec<HoconValue>>,
) -> Result<Hocon, crate::Error> {
match self {
HoconValue::Null(_) => Ok(Hocon::Null),
Expand Down Expand Up @@ -114,7 +115,15 @@ impl HoconValue {
}
(_, v) => v,
})
.map(|v| v.finalize(root, config, true, included_path.clone()))
.map(|v| {
v.finalize(
root,
config,
true,
included_path.clone(),
substituting_path.clone(),
)
})
.filter_map(|v| v.ok().and_then(|v| v.as_internal_string()))
.collect::<Vec<String>>()
.join("")
Expand All @@ -136,39 +145,45 @@ impl HoconValue {
} else {
v.to_path()
};
match (
config.strict,
config.system,
root.tree
.find_key(config, fixed_up_path)
.and_then(|v| v.finalize(root, config, included_path)),
) {
(_, true, Err(err)) | (_, true, Ok(Hocon::BadValue(err))) => {
match (
std::env::var(
v.to_path()
.into_iter()
.map(HoconValue::string_value)
.collect::<Vec<_>>()
.join("."),
),
optional,
original,
) {
(Ok(val), _, _) => Ok(Hocon::String(val)),
(_, true, Some(val)) => val.simple_finalize(),
_ => Ok(public_bad_value_or_err!(config, err)),
if Some(fixed_up_path.clone()) == substituting_path {
Ok(Hocon::Null)
} else {
match (
config.strict,
config.system,
root.tree
.find_key(config, fixed_up_path.clone())
.and_then(|v| {
v.finalize(root, config, included_path, Some(fixed_up_path))
}),
) {
(_, true, Err(err)) | (_, true, Ok(Hocon::BadValue(err))) => {
match (
std::env::var(
v.to_path()
.into_iter()
.map(HoconValue::string_value)
.collect::<Vec<_>>()
.join("."),
),
optional,
original,
) {
(Ok(val), _, _) => Ok(Hocon::String(val)),
(_, true, Some(val)) => val.simple_finalize(),
_ => Ok(public_bad_value_or_err!(config, err)),
}
}
(true, _, Err(err)) | (true, _, Ok(Hocon::BadValue(err))) => Err(err),
(_, _, v) => v,
}
(true, _, Err(err)) | (true, _, Ok(Hocon::BadValue(err))) => Err(err),
(_, _, v) => v,
}
}
HoconValue::Included {
value,
include_root,
..
} => value.finalize(root, config, in_concat, include_root),
} => value.finalize(root, config, in_concat, include_root, None),
// These cases should have been replaced during substitution
// and not exist anymore at this point
HoconValue::Temp => unreachable!(),
Expand Down Expand Up @@ -258,7 +273,8 @@ impl HoconValue {
include_root,
} => {
match *value.clone() {
HoconValue::PathSubstitution { target: path, .. } => {
HoconValue::PathSubstitution { target: path, .. }
| HoconValue::PathSubstitutionInParent(path) => {
let root_path = at_path
.iter()
.take(at_path.len() - original_path.len())
Expand Down Expand Up @@ -329,6 +345,8 @@ impl std::hash::Hash for HoconValue {
match self {
HoconValue::Integer(i) => i.hash(state),
HoconValue::String(s) => s.hash(state),
HoconValue::UnquotedString(s) => s.hash(state),
HoconValue::Null(s) => s.hash(state),
_ => unreachable!(),
};
}
Expand Down
7 changes: 7 additions & 0 deletions tests/data/issue-26-1.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Fields = [1, 2]

WazuhParsers = [
{
Fields = ${Fields} [3]
},
]
3 changes: 3 additions & 0 deletions tests/data/issue-26-2.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include "issue-26-1.conf"
DefaultParsers = []
DefaultParsers = ${DefaultParsers}${WazuhParsers}
1 change: 1 addition & 0 deletions tests/data/issue-26-3.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a = ${?a}
5 changes: 5 additions & 0 deletions tests/snapshots/snapshot__issue-26-1.conf.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: tests/snapshot.rs
expression: stable_readable_display(&doc)
---
"{Fields: [1, 2], WazuhParsers: [{Fields: [1, 2, 3]}]}"
5 changes: 5 additions & 0 deletions tests/snapshots/snapshot__issue-26-2.conf.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: tests/snapshot.rs
expression: stable_readable_display(&doc)
---
"{DefaultParsers: \"\", Fields: [1, 2], WazuhParsers: [{Fields: [1, 2, 3]}]}"
5 changes: 5 additions & 0 deletions tests/snapshots/snapshot__issue-26-3.conf.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: tests/snapshot.rs
expression: stable_readable_display(&doc)
---
"{a: null}"

0 comments on commit fc0aa01

Please sign in to comment.