use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol 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;
}
use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol in project ballerina by ballerina-lang.
the class TypeChecker method checkInvocationParam.
private List<BType> checkInvocationParam(BLangInvocation iExpr) {
List<BType> paramTypes = ((BInvokableType) iExpr.symbol.type).getParameterTypes();
int requiredParamsCount;
if (iExpr.symbol.tag == SymTag.VARIABLE) {
// Here we assume function pointers can have only required params.
// And assume that named params and rest params are not supported.
requiredParamsCount = paramTypes.size();
} else {
requiredParamsCount = ((BInvokableSymbol) iExpr.symbol).params.size();
}
// Split the different argument types: required args, named args and rest args
int i = 0;
BLangExpression vararg = null;
for (BLangExpression expr : iExpr.argExprs) {
switch(expr.getKind()) {
case NAMED_ARGS_EXPR:
iExpr.namedArgs.add((BLangNamedArgsExpression) expr);
break;
case REST_ARGS_EXPR:
vararg = expr;
break;
default:
if (i < requiredParamsCount) {
iExpr.requiredArgs.add(expr);
} else {
iExpr.restArgs.add(expr);
}
i++;
break;
}
}
return checkInvocationArgs(iExpr, paramTypes, requiredParamsCount, vararg);
}
use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol in project ballerina by ballerina-lang.
the class TypeChecker method checkInvocationArgs.
private List<BType> checkInvocationArgs(BLangInvocation iExpr, List<BType> paramTypes, int requiredParamsCount, BLangExpression vararg) {
List<BType> actualTypes = getListWithErrorTypes(expTypes.size());
BInvokableSymbol invocableSymbol = (BInvokableSymbol) iExpr.symbol;
// Check whether the expected param count and the actual args counts are matching.
if (requiredParamsCount > iExpr.requiredArgs.size()) {
dlog.error(iExpr.pos, DiagnosticCode.NOT_ENOUGH_ARGS_FUNC_CALL, iExpr.name.value);
return actualTypes;
} else if (invocableSymbol.restParam == null && (vararg != null || !iExpr.restArgs.isEmpty())) {
dlog.error(iExpr.pos, DiagnosticCode.TOO_MANY_ARGS_FUNC_CALL, iExpr.name.value);
return actualTypes;
}
// formal parameters of the outer function.
if (iExpr.argExprs.size() == 1 && iExpr.argExprs.get(0).getKind() == NodeKind.INVOCATION) {
checkExpr(iExpr.requiredArgs.get(0), this.env, ((BInvokableType) invocableSymbol.type).paramTypes);
} else {
checkRequiredArgs(iExpr.requiredArgs, paramTypes);
}
checkNamedArgs(iExpr.namedArgs, invocableSymbol.defaultableParams);
checkRestArgs(iExpr.restArgs, vararg, invocableSymbol.restParam);
if (iExpr.async) {
return Arrays.asList(this.generateFutureType(invocableSymbol));
} else {
return invocableSymbol.type.getReturnTypes();
}
}
use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol in project ballerina by ballerina-lang.
the class Types method checkConnectorEquivalency.
public boolean checkConnectorEquivalency(BType actualType, BType expType) {
if (actualType.tag != TypeTags.CONNECTOR || expType.tag != TypeTags.CONNECTOR) {
return false;
}
if (isSameType(actualType, expType)) {
return true;
}
BConnectorType expConnectorType = (BConnectorType) expType;
BConnectorType actualConnectorType = (BConnectorType) actualType;
// take actions in connectors
List<BInvokableSymbol> expActions = symResolver.getConnectorActionSymbols(expConnectorType.tsymbol.scope);
List<BInvokableSymbol> actActions = symResolver.getConnectorActionSymbols(actualConnectorType.tsymbol.scope);
if (expActions.isEmpty() && actActions.isEmpty()) {
return true;
}
if (expActions.size() != actActions.size()) {
return false;
}
// check every action signatures are matching or not
for (BInvokableSymbol expAction : expActions) {
if (actActions.stream().filter(v -> checkActionTypeEquality(expAction, v)).collect(Collectors.toList()).size() != 1) {
return false;
}
}
return true;
}
use of org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol in project ballerina by ballerina-lang.
the class CodeGenerator method visitFunctionPointerLoad.
private void visitFunctionPointerLoad(BLangExpression fpExpr, BInvokableSymbol funcSymbol) {
int pkgRefCPIndex = addPackageRefCPEntry(currentPkgInfo, funcSymbol.pkgID);
int funcNameCPIndex = addUTF8CPEntry(currentPkgInfo, funcSymbol.name.value);
FunctionRefCPEntry funcRefCPEntry = new FunctionRefCPEntry(pkgRefCPIndex, funcNameCPIndex);
int funcRefCPIndex = currentPkgInfo.addCPEntry(funcRefCPEntry);
RegIndex nextIndex = calcAndGetExprRegIndex(fpExpr);
emit(InstructionCodes.FPLOAD, getOperand(funcRefCPIndex), nextIndex);
}
Aggregations