use of org.wso2.ballerinalang.compiler.tree.BLangInvokableNode in project ballerina by ballerina-lang.
the class SymbolEnter method defineInvokableSymbolParams.
private void defineInvokableSymbolParams(BLangInvokableNode invokableNode, BInvokableSymbol symbol, SymbolEnv invokableEnv) {
List<BVarSymbol> paramSymbols = invokableNode.requiredParams.stream().peek(varNode -> defineNode(varNode, invokableEnv)).map(varNode -> varNode.symbol).collect(Collectors.toList());
List<BVarSymbol> namedParamSymbols = invokableNode.defaultableParams.stream().peek(varDefNode -> defineNode(varDefNode.var, invokableEnv)).map(varDefNode -> varDefNode.var.symbol).collect(Collectors.toList());
List<BVarSymbol> retParamSymbols = invokableNode.retParams.stream().peek(varNode -> defineNode(varNode, invokableEnv)).filter(varNode -> varNode.symbol != null).map(varNode -> varNode.symbol).collect(Collectors.toList());
symbol.params = paramSymbols;
symbol.retParams = retParamSymbols;
symbol.defaultableParams = namedParamSymbols;
// Create function type
List<BType> paramTypes = paramSymbols.stream().map(paramSym -> paramSym.type).collect(Collectors.toList());
namedParamSymbols.forEach(paramSymbol -> paramTypes.add(paramSymbol.type));
if (invokableNode.restParam != null) {
defineNode(invokableNode.restParam, invokableEnv);
symbol.restParam = invokableNode.restParam.symbol;
paramTypes.add(symbol.restParam.type);
}
List<BType> retTypes = invokableNode.retParams.stream().map(varNode -> varNode.type != null ? varNode.type : varNode.typeNode.type).collect(Collectors.toList());
symbol.type = new BInvokableType(paramTypes, retTypes, null);
}
use of org.wso2.ballerinalang.compiler.tree.BLangInvokableNode in project ballerina by ballerina-lang.
the class TaintAnalyzer method visitInvokable.
private void visitInvokable(BLangInvokableNode invNode, SymbolEnv symbolEnv) {
if (invNode.symbol.taintTable == null) {
if (Symbols.isNative(invNode.symbol)) {
attachTaintTableBasedOnAnnotations(invNode);
return;
}
Map<Integer, TaintRecord> taintTable = new HashMap<>();
returnTaintedStatusList = null;
// Check the tainted status of return values when no parameter is tainted.
analyzeAllParamsUntaintedReturnTaintedStatus(taintTable, invNode, symbolEnv);
boolean isBlocked = processBlockedNode(invNode);
if (isBlocked) {
return;
}
int requiredParamCount = invNode.requiredParams.size();
int defaultableParamCount = invNode.defaultableParams.size();
int totalParamCount = requiredParamCount + defaultableParamCount + (invNode.restParam == null ? 0 : 1);
for (int paramIndex = 0; paramIndex < totalParamCount; paramIndex++) {
BLangVariable param = getParam(invNode, paramIndex, requiredParamCount, defaultableParamCount);
// If parameter is sensitive, it is invalid to have a case where tainted status of parameter is true.
if (hasAnnotation(param, ANNOTATION_SENSITIVE)) {
continue;
}
returnTaintedStatusList = null;
// Set each parameter "tainted", then analyze the body to observe the outcome of the function.
analyzeReturnTaintedStatus(taintTable, invNode, symbolEnv, paramIndex, requiredParamCount, defaultableParamCount);
}
invNode.symbol.taintTable = taintTable;
}
}
use of org.wso2.ballerinalang.compiler.tree.BLangInvokableNode in project ballerina by ballerina-lang.
the class TaintAnalyzer method analyzeReturnTaintedStatus.
private void analyzeReturnTaintedStatus(Map<Integer, TaintRecord> taintTable, BLangInvokableNode invokableNode, SymbolEnv symbolEnv, int paramIndex, int requiredParamCount, int defaultableParamCount) {
resetTaintedStatusOfVariables(invokableNode.requiredParams);
resetTaintedStatusOfVariableDef(invokableNode.defaultableParams);
if (invokableNode.restParam != null) {
resetTaintedStatusOfVariables(Arrays.asList(new BLangVariable[] { invokableNode.restParam }));
}
// Mark the given parameter "tainted".
if (paramIndex != ALL_UNTAINTED_TABLE_ENTRY_INDEX) {
if (paramIndex < requiredParamCount) {
invokableNode.requiredParams.get(paramIndex).symbol.tainted = true;
} else if (paramIndex < requiredParamCount + defaultableParamCount) {
invokableNode.defaultableParams.get(paramIndex - requiredParamCount).var.symbol.tainted = true;
} else {
invokableNode.restParam.symbol.tainted = true;
}
}
analyzeReturnTaintedStatus(invokableNode, symbolEnv);
if (taintErrorSet.size() > 0) {
// When invocation returns an error (due to passing a tainted argument to a sensitive parameter) add current
// error to the table for future reference.
taintTable.put(paramIndex, new TaintRecord(null, new ArrayList<>(taintErrorSet)));
taintErrorSet.clear();
} else if (this.blockedNode == null) {
if (invokableNode.retParams.size() == 0) {
returnTaintedStatusList = new ArrayList<>();
} else {
updatedReturnTaintedStatusBasedOnAnnotations(invokableNode.retParams);
}
taintTable.put(paramIndex, new TaintRecord(returnTaintedStatusList, null));
}
}
use of org.wso2.ballerinalang.compiler.tree.BLangInvokableNode in project ballerina by ballerina-lang.
the class TaintAnalyzer method attachTaintTableBasedOnAnnotations.
private void attachTaintTableBasedOnAnnotations(BLangInvokableNode invokableNode) {
if (invokableNode.symbol.taintTable == null) {
// Extract tainted status of the function by lookint at annotations added to returns.
List<Boolean> retParamsTaintedStatus = new ArrayList<>();
for (BLangVariable retParam : invokableNode.retParams) {
retParamsTaintedStatus.add(hasAnnotation(retParam, ANNOTATION_TAINTED));
}
// Append taint table with tainted status when no parameter is tainted.
Map<Integer, TaintRecord> taintTable = new HashMap<>();
taintTable.put(ALL_UNTAINTED_TABLE_ENTRY_INDEX, new TaintRecord(retParamsTaintedStatus, null));
int requiredParamCount = invokableNode.requiredParams.size();
int defaultableParamCount = invokableNode.defaultableParams.size();
int totalParamCount = requiredParamCount + defaultableParamCount + (invokableNode.restParam == null ? 0 : 1);
if (totalParamCount > 0) {
// Append taint table with tainted status when each parameter is tainted.
for (int paramIndex = 0; paramIndex < totalParamCount; paramIndex++) {
BLangVariable param = getParam(invokableNode, paramIndex, requiredParamCount, defaultableParamCount);
// If parameter is sensitive, test for this parameter being tainted is invalid.
if (hasAnnotation(param, ANNOTATION_SENSITIVE)) {
continue;
}
taintTable.put(paramIndex, new TaintRecord(retParamsTaintedStatus, null));
}
}
invokableNode.symbol.taintTable = taintTable;
}
}
use of org.wso2.ballerinalang.compiler.tree.BLangInvokableNode in project ballerina by ballerina-lang.
the class CodeAnalyzer method visitInvocable.
private void visitInvocable(BLangInvokableNode invNode) {
this.resetFunction();
this.initNewWorkerActionSystem();
if (Symbols.isNative(invNode.symbol)) {
return;
}
boolean invokableReturns = invNode.retParams.size() > 0;
if (invNode.workers.isEmpty()) {
invNode.body.accept(this);
/* the function returns, but none of the statements surely returns */
if (invokableReturns && !this.statementReturns) {
this.dlog.error(invNode.pos, DiagnosticCode.INVOKABLE_MUST_RETURN, invNode.getKind().toString().toLowerCase());
}
} else {
boolean workerReturns = false;
for (BLangWorker worker : invNode.workers) {
worker.accept(this);
workerReturns = workerReturns || this.statementReturns;
this.resetStatementReturns();
}
if (invokableReturns && !workerReturns) {
this.dlog.error(invNode.pos, DiagnosticCode.ATLEAST_ONE_WORKER_MUST_RETURN, invNode.getKind().toString().toLowerCase());
}
}
this.finalizeCurrentWorkerActionSystem();
}
Aggregations