golemcloud / golem

Golem is an open source durable computing platform that makes it easy to build and deploy highly reliable distributed systems.
https://learn.golem.cloud/
Apache License 2.0
214 stars 22 forks source link

Investigate stack overflow for a specific expression #794

Open afsalthaj opened 3 weeks ago

afsalthaj commented 3 weeks ago

This comes from the parser!

async fn test_evaluation_with_request_body_select_index() {
        let noop_executor = DefaultEvaluator::noop();

        let request_details = get_request_details(
            r#"
                    {

                           "id": "bId",
                           "name": "bName",
                           "titles": [
                             "bTitle1", "bTitle2"
                           ],
                           "address": {
                             "street": "bStreet",
                             "city": "bCity"
                           }

                    }"#,
            &HeaderMap::new(),
        );

        // The spec that will become part of the component metadata
        let request_body_type = get_analysed_type_record(vec![
            ("id".to_string(), AnalysedType::Str(TypeStr)),
            ("name".to_string(), AnalysedType::Str(TypeStr)),
            (
                "titles".to_string(),
                AnalysedType::List(TypeList {
                    inner: Box::new(AnalysedType::Str(TypeStr)),
                }),
            ),
            (
                "address".to_string(),
                get_analysed_type_record(vec![
                    ("street".to_string(), AnalysedType::Str(TypeStr)),
                    ("city".to_string(), AnalysedType::Str(TypeStr)),
                ]),
            ),
        ]);

        let request_type =
            get_analysed_type_record(vec![("body".to_string(), request_body_type.clone())]);

        // Output from worker - doesn't matter
        let worker_response = create_none(Some(&AnalysedType::Str(TypeStr)));

        // Output from worker
        let return_type = AnalysedType::Option(TypeOption {
            inner: Box::new(AnalysedType::try_from(&worker_response).unwrap()),
        });

        let component_metadata =
            get_analysed_exports("foo", vec![request_type.clone()], return_type);

        let expr_str = r#"${
              let x = { body : { id: "bId", name: "bName", titles: request.body.titles, address: request.body.address } };
              let result = foo(x);
              call(x)
            }"#;

        let expr1 = rib::from_string(expr_str).unwrap();
        let result = noop_executor
            .evaluate_with_worker_response(
                &expr1,
                worker_response.clone(),
                component_metadata.clone(),
                Some((request_details, request_type)),
            )
            .await
            .unwrap();

        assert_eq!(result, TypeAnnotatedValue::Str("bTitle2".to_string()));
    }
afsalthaj commented 3 weeks ago

Ah!, the stack overflow is indeed in the parser

        let input = { body: { id: "bId", name: "bName", titles: request.body.titles, address: request.body.address } };
              let result = foo(input);

this works, while the following blows stack!

        let result = foo( { body: { id: "bId", name: "bName", titles: request.body.titles, address: request.body.address } });
afsalthaj commented 2 weeks ago

In fact, the following test which failed only in CI came up with this error for record-of-record

thread 'text::record_tests::test_round_trip_read_write_record_of_record' has overflowed its stack
fatal runtime error: stack overflow
error: test failed, to rerun pass `-p golem-rib --lib`