Keats / tera

A template engine for Rust based on Jinja2/Django
http://keats.github.io/tera/
MIT License
3.43k stars 279 forks source link

Large 64-bit unsigned ints in template functions result in out of bounds error #851

Open Philosobyte opened 1 year ago

Philosobyte commented 1 year ago

A template which contains a large unsigned 64-bit integer as a function argument will fail to parse with a "Integer out of bounds" error:

called `Result::unwrap()` on an `Err` value: Error { kind: Msg("Failed to parse '__tera_one_off'"), source: Some(Error { kind: Msg("Integer out of bounds: `18446744073709551600`"), source: None }) }

Here is a test which reproduces the issue:

#[cfg(test)]
mod tests {
    use tera::{Context, Tera};

    #[test]
    fn u64_bug_test() {
        let mut tera: Tera = Tera::default();
        let context: Context = Context::new();

        tera.register_function("print_u64", print_u64);

        let input_template_str = "{{ print_u64(value=18446744073709551600) }}";
        let render_result: String = tera.render_str(input_template_str, &context).unwrap();
        println!("render_result: {render_result}");
    }

    fn print_u64(args: &HashMap<String, Value>) -> tera::Result<Value> {
        let value: u64 = args.get("value")
            .cloned()
            .and_then(|value: Value| from_value(value).ok())
            .unwrap();

        println!("value: {value}");
        let json_value: Value = to_value(value)?;
        Ok(json_value)
    }
}

To add some speculation, I believe the error is happening in the Template::new function. It is likely in the parse call in the first line of that function. I don't know yet whether the error is the fault of the pest parser or the way Tera uses it. It could also be the way Tera uses serde_json, but some basic testing shows that serde_json itself should handle u64s OK.

Keats commented 1 year ago

Probably the parser. Once I've implemented functions I'll check in tera v2 but we have complete control of the parser/Value type so it would be easy to handle

Philosobyte commented 1 year ago

Probably the parser. Once I've implemented functions I'll check in tera v2 but we have complete control of the parser/Value type so it would be easy to handle

Thank you!