Search in sources :

Example 1 with BLangInvocation

use of org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation in project ballerina by ballerina-lang.

the class SymbolEnter method createInitFuncInvocationStmt.

private BLangExpressionStmt createInitFuncInvocationStmt(BLangImportPackage importPackage, BInvokableSymbol initFunctionSymbol) {
    BLangInvocation invocationNode = (BLangInvocation) TreeBuilder.createInvocationNode();
    invocationNode.pos = importPackage.pos;
    invocationNode.addWS(importPackage.getWS());
    BLangIdentifier funcName = (BLangIdentifier) TreeBuilder.createIdentifierNode();
    funcName.value = initFunctionSymbol.name.value;
    invocationNode.name = funcName;
    invocationNode.pkgAlias = importPackage.alias;
    BLangExpressionStmt exprStmt = (BLangExpressionStmt) TreeBuilder.createExpressionStatementNode();
    exprStmt.pos = importPackage.pos;
    exprStmt.addWS(importPackage.getWS());
    exprStmt.expr = invocationNode;
    return exprStmt;
}
Also used : BLangIdentifier(org.wso2.ballerinalang.compiler.tree.BLangIdentifier) BLangInvocation(org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation) BLangExpressionStmt(org.wso2.ballerinalang.compiler.tree.statements.BLangExpressionStmt)

Example 2 with BLangInvocation

use of org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation in project ballerina by ballerina-lang.

the class TaintAnalyzer method analyzeInvocation.

// Private methods relevant to invocation analysis.
private void analyzeInvocation(BLangInvocation invocationExpr) {
    BInvokableSymbol invokableSymbol = (BInvokableSymbol) invocationExpr.symbol;
    Map<Integer, TaintRecord> taintTable = invokableSymbol.taintTable;
    List<Boolean> returnTaintedStatus = new ArrayList<>();
    TaintRecord allParamsUntaintedRecord = taintTable.get(ALL_UNTAINTED_TABLE_ENTRY_INDEX);
    if (allParamsUntaintedRecord.taintError != null && allParamsUntaintedRecord.taintError.size() > 0) {
        // This can occur when there is a error regardless of tainted status of parameters.
        // Example: Tainted value returned by function is passed to another functions's sensitive parameter.
        addTaintError(allParamsUntaintedRecord.taintError);
    } else {
        returnTaintedStatus = new ArrayList<>(taintTable.get(ALL_UNTAINTED_TABLE_ENTRY_INDEX).retParamTaintedStatus);
    }
    if (invocationExpr.argExprs != null) {
        for (int argIndex = 0; argIndex < invocationExpr.argExprs.size(); argIndex++) {
            BLangExpression argExpr = invocationExpr.argExprs.get(argIndex);
            argExpr.accept(this);
            // return-tainted-status when the given argument is in tainted state.
            if (getObservedTaintedStatus()) {
                TaintRecord taintRecord = taintTable.get(argIndex);
                if (taintRecord == null) {
                    // This is when current parameter is "sensitive". Therefore, providing a tainted
                    // value to a sensitive parameter is invalid and should return a compiler error.
                    int requiredParamCount = invokableSymbol.params.size();
                    int defaultableParamCount = invokableSymbol.defaultableParams.size();
                    int totalParamCount = requiredParamCount + defaultableParamCount + (invokableSymbol.restParam == null ? 0 : 1);
                    BVarSymbol paramSymbol = getParamSymbol(invokableSymbol, argIndex, requiredParamCount, defaultableParamCount);
                    addTaintError(argExpr.pos, paramSymbol.name.value, DiagnosticCode.TAINTED_VALUE_PASSED_TO_SENSITIVE_PARAMETER);
                } else if (taintRecord.taintError != null && taintRecord.taintError.size() > 0) {
                    // This is when current parameter is derived to be sensitive. The error already generated
                    // during taint-table generation will be used.
                    addTaintError(taintRecord.taintError);
                } else {
                    // status of all returns to get accumulated tainted status of all returns for the invocation.
                    for (int returnIndex = 0; returnIndex < returnTaintedStatus.size(); returnIndex++) {
                        if (taintRecord.retParamTaintedStatus.get(returnIndex)) {
                            returnTaintedStatus.set(returnIndex, true);
                        }
                    }
                }
                if (stopAnalysis) {
                    break;
                }
            }
        }
    }
    if (invocationExpr.expr != null) {
        // When an invocation like stringValue.trim() happens, if stringValue is tainted, the result will
        // also be tainted.
        // TODO: TaintedIf annotation, so that it's possible to define what can taint or untaint the return.
        invocationExpr.expr.accept(this);
        for (int i = 0; i < returnTaintedStatus.size(); i++) {
            if (getObservedTaintedStatus()) {
                returnTaintedStatus.set(i, getObservedTaintedStatus());
            }
        }
    }
    taintedStatusList = returnTaintedStatus;
}
Also used : ArrayList(java.util.ArrayList) BInvokableSymbol(org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol) TaintRecord(org.wso2.ballerinalang.compiler.semantics.model.symbols.TaintRecord) BLangExpression(org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression) BLangEndpoint(org.wso2.ballerinalang.compiler.tree.BLangEndpoint) BVarSymbol(org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol)

Example 3 with BLangInvocation

use of org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation in project ballerina by ballerina-lang.

the class TaintAnalyzer method analyzeLambdaExpressions.

private void analyzeLambdaExpressions(BLangInvocation invocationExpr, BLangExpression argExpr) {
    BLangFunction function = ((BLangLambdaFunction) argExpr).function;
    if (function.symbol.taintTable == null) {
        addToBlockedList(invocationExpr);
    } else {
        int requiredParamCount = function.requiredParams.size();
        int defaultableParamCount = function.defaultableParams.size();
        int totalParamCount = requiredParamCount + defaultableParamCount + (function.restParam == null ? 0 : 1);
        Map<Integer, TaintRecord> taintTable = function.symbol.taintTable;
        for (int paramIndex = 0; paramIndex < totalParamCount; paramIndex++) {
            TaintRecord taintRecord = taintTable.get(paramIndex);
            BLangVariable param = getParam(function, paramIndex, requiredParamCount, defaultableParamCount);
            if (taintRecord == null) {
                addTaintError(argExpr.pos, param.name.value, DiagnosticCode.TAINTED_VALUE_PASSED_TO_SENSITIVE_PARAMETER);
            } else if (taintRecord.taintError != null && taintRecord.taintError.size() > 0) {
                addTaintError(taintRecord.taintError);
            }
            if (stopAnalysis) {
                break;
            }
        }
    }
}
Also used : BLangFunction(org.wso2.ballerinalang.compiler.tree.BLangFunction) BLangLambdaFunction(org.wso2.ballerinalang.compiler.tree.expressions.BLangLambdaFunction) TaintRecord(org.wso2.ballerinalang.compiler.semantics.model.symbols.TaintRecord) BLangEndpoint(org.wso2.ballerinalang.compiler.tree.BLangEndpoint) BLangVariable(org.wso2.ballerinalang.compiler.tree.BLangVariable)

Example 4 with BLangInvocation

use of org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation in project ballerina by ballerina-lang.

the class TypeChecker method visit.

public void visit(BLangInvocation iExpr) {
    // e.g. foo();, foo(), foo().k;
    if (iExpr.expr == null) {
        // This is a function invocation expression. e.g. foo()
        checkFunctionInvocationExpr(iExpr);
        return;
    }
    Name pkgAlias = names.fromIdNode(iExpr.pkgAlias);
    if (pkgAlias != Names.EMPTY) {
        dlog.error(iExpr.pos, DiagnosticCode.PKG_ALIAS_NOT_ALLOWED_HERE);
        return;
    }
    // Find the variable reference expression type
    final List<BType> exprTypes = checkExpr(iExpr.expr, this.env, Lists.of(symTable.noType));
    if (isIterableOperationInvocation(iExpr)) {
        iExpr.iterableOperationInvocation = true;
        iterableAnalyzer.handlerIterableOperation(iExpr, expTypes.isEmpty() ? symTable.voidType : expTypes.get(0), env);
        if (iExpr.iContext.operations.getLast().resultType == symTable.voidType) {
            resultTypes = Collections.emptyList();
        } else {
            resultTypes = Lists.of(iExpr.iContext.operations.getLast().resultType);
        }
        return;
    }
    if (iExpr.actionInvocation) {
        if (exprTypes.size() != 1) {
            dlog.error(iExpr.expr.pos, DiagnosticCode.SINGLE_VALUE_RETURN_EXPECTED);
        }
        checkActionInvocationExpr(iExpr, exprTypes.size() > 0 ? exprTypes.get(0) : symTable.errType);
        return;
    }
    switch(iExpr.expr.type.tag) {
        case TypeTags.STRUCT:
            // Invoking a function bound to a struct
            // First check whether there exist a function with this name
            // Then perform arg and param matching
            checkFunctionInvocationExpr(iExpr, (BStructType) iExpr.expr.type);
            break;
        case TypeTags.CONNECTOR:
            dlog.error(iExpr.pos, DiagnosticCode.INVALID_ACTION_INVOCATION_SYNTAX);
            resultTypes = getListWithErrorTypes(expTypes.size());
            return;
        case TypeTags.BOOLEAN:
        case TypeTags.STRING:
        case TypeTags.INT:
        case TypeTags.FLOAT:
        case TypeTags.BLOB:
        case TypeTags.XML:
            checkFunctionInvocationExpr(iExpr, iExpr.expr.type);
            break;
        case TypeTags.JSON:
            checkFunctionInvocationExpr(iExpr, symTable.jsonType);
            break;
        case TypeTags.TABLE:
            checkFunctionInvocationExpr(iExpr, symTable.tableType);
            break;
        case TypeTags.STREAM:
            checkFunctionInvocationExpr(iExpr, symTable.streamType);
            break;
        case TypeTags.FUTURE:
            checkFunctionInvocationExpr(iExpr, symTable.futureType);
            break;
        case TypeTags.NONE:
            dlog.error(iExpr.pos, DiagnosticCode.UNDEFINED_FUNCTION, iExpr.name);
            break;
        case TypeTags.MAP:
            // allow map function for both constrained / un constrained maps
            checkFunctionInvocationExpr(iExpr, this.symTable.mapType);
            break;
        case TypeTags.ERROR:
            break;
        case TypeTags.INTERMEDIATE_COLLECTION:
            dlog.error(iExpr.pos, DiagnosticCode.INVALID_FUNCTION_INVOCATION_WITH_NAME, iExpr.name, iExpr.expr.type);
            resultTypes = getListWithErrorTypes(expTypes.size());
            break;
        default:
            dlog.error(iExpr.pos, DiagnosticCode.INVALID_FUNCTION_INVOCATION, iExpr.expr.type);
            resultTypes = getListWithErrorTypes(expTypes.size());
            break;
    }
// TODO other types of invocation expressions
// TODO pkg alias should be null or empty here.
}
Also used : BType(org.wso2.ballerinalang.compiler.semantics.model.types.BType) BLangXMLQName(org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLQName) Name(org.wso2.ballerinalang.compiler.util.Name)

Example 5 with BLangInvocation

use of org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation in project ballerina by ballerina-lang.

the class CodeAnalyzer method visit.

public void visit(BLangInvocation invocationExpr) {
    analyzeExpr(invocationExpr.expr);
    analyzeExprs(invocationExpr.requiredArgs);
    analyzeExprs(invocationExpr.namedArgs);
    analyzeExprs(invocationExpr.restArgs);
    checkDuplicateNamedArgs(invocationExpr.namedArgs);
    // Null check is to ignore Negative path where symbol does not get resolved at TypeChecker.
    if ((invocationExpr.symbol != null) && invocationExpr.symbol.kind == SymbolKind.FUNCTION) {
        BSymbol funcSymbol = invocationExpr.symbol;
        if (Symbols.isFlagOn(funcSymbol.flags, Flags.DEPRECATED)) {
            dlog.warning(invocationExpr.pos, DiagnosticCode.USAGE_OF_DEPRECATED_FUNCTION, names.fromIdNode(invocationExpr.name));
        }
    }
}
Also used : BSymbol(org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol)

Aggregations

BLangInvocation (org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation)22 BLangExpression (org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression)12 ArrayList (java.util.ArrayList)11 BType (org.wso2.ballerinalang.compiler.semantics.model.types.BType)9 Name (org.wso2.ballerinalang.compiler.util.Name)8 BSymbol (org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol)7 DiagnosticPos (org.wso2.ballerinalang.compiler.util.diagnotic.DiagnosticPos)6 BLangEndpoint (org.wso2.ballerinalang.compiler.tree.BLangEndpoint)5 BLangVariable (org.wso2.ballerinalang.compiler.tree.BLangVariable)5 List (java.util.List)4 BInvokableSymbol (org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol)4 BLangFunction (org.wso2.ballerinalang.compiler.tree.BLangFunction)4 BLangPackage (org.wso2.ballerinalang.compiler.tree.BLangPackage)4 BLangXMLQName (org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLQName)4 BLangExpressionStmt (org.wso2.ballerinalang.compiler.tree.statements.BLangExpressionStmt)4 Paths (java.nio.file.Paths)3 HashMap (java.util.HashMap)3 Map (java.util.Map)3 DocumentServiceKeys (org.ballerinalang.langserver.DocumentServiceKeys)3 TextDocumentServiceContext (org.ballerinalang.langserver.TextDocumentServiceContext)3