Fix stack overflow when printing tables with cyclic references (#158)

This commit is contained in:
Erica Marigold 2024-03-11 22:27:44 +05:30 committed by GitHub
parent 20b9fce7df
commit 1f211ca0ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -103,9 +103,9 @@ pub fn style_from_style_str<S: AsRef<str>>(s: S) -> LuaResult<Option<&'static St
pub fn pretty_format_value( pub fn pretty_format_value(
buffer: &mut String, buffer: &mut String,
value: &LuaValue, value: &LuaValue,
parent_table_addr: Option<String>,
depth: usize, depth: usize,
) -> std::fmt::Result { ) -> std::fmt::Result {
// TODO: Handle tables with cyclic references
match &value { match &value {
LuaValue::Nil => write!(buffer, "nil")?, LuaValue::Nil => write!(buffer, "nil")?,
LuaValue::Boolean(true) => write!(buffer, "{}", COLOR_YELLOW.apply_to("true"))?, LuaValue::Boolean(true) => write!(buffer, "{}", COLOR_YELLOW.apply_to("true"))?,
@ -123,10 +123,14 @@ pub fn pretty_format_value(
) )
)?, )?,
LuaValue::Table(ref tab) => { LuaValue::Table(ref tab) => {
let table_addr = Some(format!("{:p}", tab.to_pointer()));
if depth >= MAX_FORMAT_DEPTH { if depth >= MAX_FORMAT_DEPTH {
write!(buffer, "{}", STYLE_DIM.apply_to("{ ... }"))?; write!(buffer, "{}", STYLE_DIM.apply_to("{ ... }"))?;
} else if let Some(s) = call_table_tostring_metamethod(tab) { } else if let Some(s) = call_table_tostring_metamethod(tab) {
write!(buffer, "{s}")?; write!(buffer, "{s}")?;
} else if depth >= 1 && parent_table_addr.eq(&table_addr) {
write!(buffer, "{}", STYLE_DIM.apply_to("<self>"))?
} else { } else {
let mut is_empty = false; let mut is_empty = false;
let depth_indent = INDENT.repeat(depth); let depth_indent = INDENT.repeat(depth);
@ -144,11 +148,11 @@ pub fn pretty_format_value(
)?, )?,
_ => { _ => {
write!(buffer, "\n{depth_indent}{INDENT}[")?; write!(buffer, "\n{depth_indent}{INDENT}[")?;
pretty_format_value(buffer, &key, depth)?; pretty_format_value(buffer, &key, parent_table_addr.clone(), depth)?;
write!(buffer, "] {} ", STYLE_DIM.apply_to("="))?; write!(buffer, "] {} ", STYLE_DIM.apply_to("="))?;
} }
} }
pretty_format_value(buffer, &value, depth + 1)?; pretty_format_value(buffer, &value, parent_table_addr.clone(), depth + 1)?;
write!(buffer, "{}", STYLE_DIM.apply_to(","))?; write!(buffer, "{}", STYLE_DIM.apply_to(","))?;
is_empty = false; is_empty = false;
} }
@ -192,7 +196,9 @@ pub fn pretty_format_multi_value(multi: &LuaMultiValue) -> LuaResult<String> {
if let LuaValue::String(s) = value { if let LuaValue::String(s) = value {
write!(buffer, "{}", s.to_string_lossy()).into_lua_err()?; write!(buffer, "{}", s.to_string_lossy()).into_lua_err()?;
} else { } else {
pretty_format_value(&mut buffer, value, 0).into_lua_err()?; let addr = format!("{:p}", value.to_pointer());
pretty_format_value(&mut buffer, value, Some(addr), 0).into_lua_err()?;
} }
if counter < multi.len() { if counter < multi.len() {
write!(&mut buffer, " ").into_lua_err()?; write!(&mut buffer, " ").into_lua_err()?;