ballerina-platform / ballerina-lang

The Ballerina Programming Language
https://ballerina.io/
Apache License 2.0
3.68k stars 751 forks source link

[Bug]: NPE in `BIRBasicBlockOptimizer` #42327

Closed mindula closed 3 months ago

mindula commented 7 months ago

Description

Getting a null pointer exception when executing the code below.

Steps to Reproduce

import ballerina/io;
import ballerina/http;
import ballerina/lang.runtime;

configurable string environmentId = ?;
configurable string token = ?;

type BuildsItem record {
    string buildId;
    string componentId;
    string mediationComponentId;
    string commitHash;
    string componentName;
    string mediationComponentVersionId;
    string apiId;
    string revisionId;
    string status;
    boolean mediationAttached;
    string startedAt;
    string finishedAt;
};

type BuildArray record {
    BuildsItem[] builds;
    int count;
    int 'limit;
};

public function main() returns error? {

    do {

        stream<string[], io:Error?> csvStream = check io:fileReadCsvAsStream("apiInformation-CRP.csv");

        // Iterates through the stream and prints the content.
        check csvStream.forEach(function(string[] apiInfo) {

            string apiName = apiInfo[0].trim();
            string apiVersion = apiInfo[1].trim();
            string componentID = apiInfo[2].trim();
            string versionID = apiInfo[3].trim();

            json invokeInitiateDeployment = check initiateDeployment(componentID, versionID, environmentId);

            io:println("Initiated interceptor app generation for API: ", apiName, " Version: ", apiVersion, "result: ", invokeInitiateDeployment);

            runtime:sleep(60.0);

            string buildID = check getLatestBuildID(componentID, versionID);

            io:println("Latest build ID for API: ", apiName, " Version: ", apiVersion, " is: ", buildID);

            runtime:sleep(5.0);

            json invokeDeployService = check deployService(componentID, versionID, environmentId, buildID);

            io:println("Initiated deployment for the interceptor app for API: ", apiName, " Version: ", apiVersion, "result: ", invokeDeployService);

            runtime:sleep(20.0);

        });

    } on fail error e {

        io:println("Error occurred while processing: ", e);
        runtime:sleep(5.0);

    }

}

function initiateDeployment(string componentID, string versionID, string environmentID) returns json|error {

    do {

        http:Client httpEp = check new (url = string `https://app.choreo.dev/proxy/deployer/v1/components/${componentID}/versions/${versionID}/initiate-deployment?environmentId=${environmentID}&accessMode=external`, config = {
            auth: {
                token: token
            }
        });

        http:Response returnResponse = check httpEp->/.post({});

        if returnResponse.statusCode == 200 {
            json response = check returnResponse.getJsonPayload();
            return response;
        } else {
            return error(string `Error occurred while deploying Reason ${returnResponse.statusCode}`);
        }

    } on fail error e {
        return error(string `Error occurred while deploying Reaseon = ${e.toString()}`);
    }

}

function deployService(string componentID, string versionID, string environmentID, string buildID) returns json|error {

    do {

        http:Client httpEp = check new (url = string `https://app.choreo.dev/proxy/deployer/v1/components/${componentID}/versions/${versionID}/deploy-service?buildId=${buildID}&environmentId=${environmentID}&accessMode=external`, config = {
            auth: {
                token: token
            }
        });

        http:Response returnResponse = check httpEp->post(message = {}, path = "");

        if returnResponse.statusCode == 200 {
            json response = check returnResponse.getJsonPayload();
            return response;
        } else {
            return error(string `Error occurred while deploying Reason ${returnResponse.statusCode}`);
        }

    } on fail error e {
        return error(string `Error occurred while deploying Reaseon = ${e.toString()}`);
    }

}

function getLatestBuildID(string componentID, string versionID) returns string|error {

    do {

        http:Client httpEp = check new (url = string `https://app.choreo.dev/proxy/deployer/v1/components/${componentID}/versions/${versionID}/builds?limit=1`, config = {
            auth: {
                token: token
            }
        });

        http:Response returnResponse = check httpEp->get("");

        if returnResponse.statusCode == 200 {
            json response = check returnResponse.getJsonPayload();

            BuildArray payloadRecord = check response.cloneWithType();

            string buildID = payloadRecord.builds[0].buildId;

            return buildID;
        } else {

            return error(string `Error occurred while getting build information ${returnResponse.statusCode}`);
        }

    } on fail error e {
        return error(string `Error occurred while deploying Reaseon = ${e.toString()}`);
    }

}

Affected Version(s)

No response

OS, DB, other environment details and versions

No response

Related area

-> Compilation

Related issue(s) (optional)

Suggested label(s) (optional)

No response

Suggested assignee(s) (optional)

No response

mindula commented 4 months ago
function getVal(string s) returns string|error {
    return "";
}
function getVal2(function s = function () {
    do {function k = function () {string aa = check getVal("");};} on fail {
}}) returns string|error {
    return "";
}

The issue occurs when a check expression is used inside a lambda function. For the check expression in the above scenario, we should suggest the invalid usage of the 'check' expression operator compilation error. In the BLangFunction visit method in CodeAnalyzer.java, we check if the function is a lambda function and if it is, we return early. As a result of that, the body of the function in not being visited which is why we're not getting the compilation error for the check expression.

github-actions[bot] commented 3 months ago

This issue is NOT closed with a proper Reason/ label. Make sure to add proper reason label before closing. Please add or leave a comment with the proper reason label now.

      - Reason/EngineeringMistake - The issue occurred due to a mistake made in the past.
      - Reason/Regression - The issue has introduced a regression.
      - Reason/MultipleComponentInteraction - Issue occured due to interactions in multiple components.
      - Reason/Complex - Issue occurred due to complex scenario.
      - Reason/Invalid - Issue is invalid.
      - Reason/Other - None of the above cases.