/// <summary> /// For arguments passed by reference: it assignes new values, and copies flags form inputValues. /// </summary> /// <param name="flow">FlowController</param> /// <param name="inputValues">Input values into analyzed function</param> /// <param name="nativeFunctions">Info about analyzed function</param> /// <returns>List of assigned values into aliases</returns> public static List <Value> ResolveAliasArguments(FlowController flow, List <Value> inputValues, List <NativeFunction> nativeFunctions) { List <Value> result = new List <Value>(); MemoryEntry argc = flow.InSet.ReadVariable(new VariableIdentifier(".argument_count")).ReadMemory(flow.OutSet.Snapshot); int argumentCount = ((IntegerValue)argc.PossibleValues.ElementAt(0)).Value; foreach (var nativeFunction in nativeFunctions) { if (nativeFunction.MinArgumentCount <= argumentCount && nativeFunction.MaxArgumentCount >= argumentCount) { int functionArgumentNumber = 0; for (int i = 0; i < argumentCount; i++) { MemoryEntry arg = flow.InSet.ReadVariable(Argument(i)).ReadMemory(flow.InSet.Snapshot); NativeFunctionArgument functionArgument = nativeFunction.Arguments.ElementAt(functionArgumentNumber); if (functionArgument.ByReference == true) { MemoryEntry res = NativeAnalyzerUtils.ResolveReturnValue(functionArgument.Type, flow); res = new MemoryEntry(FlagsHandler.CopyFlags(inputValues, res.PossibleValues)); flow.OutSet.GetVariable(Argument(i)).WriteMemory(flow.OutSet.Snapshot, res); result.AddRange(res.PossibleValues); } //incremeneting functionArgumentNumber if (nativeFunction.Arguments.ElementAt(functionArgumentNumber).Dots == false) { functionArgumentNumber++; } } } } return(result); }
/// <summary> /// Checks arguments in functions and generates warning if the arguments don't match. /// </summary> /// <param name="flow">FlowController</param> /// <param name="nativeFunctions">nativeFunctions</param> public static void checkArgumentTypes(FlowController flow, List <NativeFunction> nativeFunctions) { List <List <AnalysisWarning> > warningsList = new List <List <AnalysisWarning> >(); MemoryEntry argc = flow.InSet.ReadVariable(new VariableIdentifier(".argument_count")).ReadMemory(flow.OutSet.Snapshot); int argumentCount = ((IntegerValue)argc.PossibleValues.ElementAt(0)).Value; foreach (var nativeFunction in nativeFunctions) { if (nativeFunction.MinArgumentCount <= argumentCount && nativeFunction.MaxArgumentCount >= argumentCount) { warningsList.Add(new List <AnalysisWarning>()); int functionArgumentNumber = 0; for (int i = 0; i < argumentCount; i++) { MemoryEntry arg = flow.InSet.ReadVariable(Argument(i)).ReadMemory(flow.InSet.Snapshot); NativeFunctionArgument functionArgument = nativeFunction.Arguments.ElementAt(functionArgumentNumber); CheckArgumentTypes(flow, arg, functionArgument, i + 1, nativeFunctions.ElementAt(0).Name.ToString(), warningsList.Last()); //incremeneting functionArgumentNumber if (nativeFunction.Arguments.ElementAt(functionArgumentNumber).Dots == false) { functionArgumentNumber++; } } } } int index_min = -1; int value_min = int.MaxValue; for (int i = 0; i < warningsList.Count; i++) { if (warningsList[i].Count < value_min) { value_min = warningsList[i].Count; index_min = i; } } foreach (AnalysisWarning warning in warningsList[index_min]) { AnalysisWarningHandler.SetWarning(flow.OutSet, warning); } }
/// <summary> /// Check type of one argument and reports warnings if they doesn't match. /// </summary> /// <param name="flow">FlowController</param> /// <param name="memoryEntry">Values of argument</param> /// <param name="argument">Information about argument</param> /// <param name="argumentNumber">Number of argument</param> /// <param name="functionName">Name of function</param> /// <param name="warnings">List of warnings, for inserting warnings</param> private static void CheckArgumentTypes(FlowController flow, MemoryEntry memoryEntry, NativeFunctionArgument argument, int argumentNumber, string functionName, List <AnalysisWarning> warnings) { bool argumentMatches = true; foreach (Value value in memoryEntry.PossibleValues) { if (value is AnyValue || value is UndefinedValue) { continue; } switch (argument.Type) { case "mixed": break; case "int": case "integer": //TODO: workaround: type declarations in .xml files specifies the arguments that should be of type number by type int // fix declarations in xml files!! //if (!(ValueTypeResolver.IsInt(value) || ValueTypeResolver.IsLong(value))) if (!(ValueTypeResolver.IsInt(value) || ValueTypeResolver.IsLong(value) || ValueTypeResolver.IsFloat(value))) { argumentMatches = false; } break; case "float": case "number": if (!(ValueTypeResolver.IsInt(value) || ValueTypeResolver.IsLong(value) || ValueTypeResolver.IsFloat(value))) { argumentMatches = false; } break; case "string": case "char": if (!ValueTypeResolver.IsString(value)) { argumentMatches = false; } break; case "array": if (!ValueTypeResolver.IsArray(value)) { argumentMatches = false; } break; case "object": if (!ValueTypeResolver.IsObject(value)) { argumentMatches = false; } break; case "bool": case "boolean": if (!ValueTypeResolver.IsBool(value)) { argumentMatches = false; } break; case "resource": case "resouce": if (!(value is AnyResourceValue)) { argumentMatches = false; } break; case "callable": case "callback": if (!ValueTypeResolver.IsString(value) && !(value is FunctionValue)) { argumentMatches = false; } break; case "void": throw new Exception("Void is not a type of argument"); default: if (!ValueTypeResolver.IsObject(value)) { argumentMatches = false; } break; } } if (argumentMatches == false) { warnings.Add(new AnalysisWarning(NativeAnalyzerUtils.GetCallerScript(flow.OutSet), "Wrong type of argument number " + argumentNumber + " in function " + functionName + ", expecting " + argument.Type, flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.WRONG_ARGUMENTS_TYPE)); } }