/// <inheritdoc /> public override MemoryEntry ReadAnyValueIndex(AnyValue value, MemberIdentifier index) { // TODO: Copy info if (value is AnyStringValue) { // Element of string is one charachter but since PHP has no character type, // it returns string with one character. The character do not need to be initialized SetWarning("Possibly uninitialized string offset"); return(new MemoryEntry(Context.AnyStringValue)); } else if ((value is AnyNumericValue) || (value is AnyBooleanValue) || (value is AnyResourceValue)) { SetWarning("Trying to get element of scalar value", AnalysisWarningCause.ELEMENT_OF_NON_ARRAY_VARIABLE); return(new MemoryEntry(Context.UndefinedValue)); } else if (value is AnyObjectValue) { // TODO: This must be error SetWarning("Cannot use object as array"); return(new MemoryEntry(Context.AnyValue)); } else { // This is case of AnyArrayValue, AnyValue and possibly others. // If value is AnyValue, it can be any object too, so it can cause an error. Value newValue = Context.AnyValue; newValue = FlagsHandler.CopyFlags(value, newValue); return(new MemoryEntry(newValue, Context.UndefinedValue)); } }
/// <summary> /// Widens given values /// </summary> /// <param name="previousIterationValues">original values from the previous iteration</param> /// <param name="currentIterationValues">values to widen</param> /// <param name="Context">Snapshot</param> /// <returns>Memory entry with widen values</returns> public MemoryEntry Widen(IEnumerable <Value> previousIterationValues, IEnumerable <Value> currentIterationValues, SnapshotBase Context) { flags = FlagsHandler.GetFlags(currentIterationValues); preservedValues = new List <Value> (currentIterationValues.Count()); notPreservedValuesBeforeWidening = new List <Value> (currentIterationValues); foreach (var value in currentIterationValues) { value.Accept(this); } return(GetResult(previousIterationValues, Context)); }
/// <inheritdoc /> public override IEnumerable <Value> WriteStringIndex(StringValue indexed, MemberIdentifier index, MemoryEntry writtenValue) { HashSet <Value> result = new HashSet <Value>(); SimpleStringConverter converter = new SimpleStringConverter(Context); bool isConcrete = false; foreach (var value in converter.Evaluate(writtenValue.PossibleValues, out isConcrete)) { string WrittenChar = value.Value; foreach (var number in ResolveStringIndex(indexed, index)) { Value newValue; if (number < 0) { newValue = indexed; SetWarning("Cannot index string with negative numbers", AnalysisWarningCause.INDEX_OUT_OF_RANGE); } else if (number < indexed.Value.Count()) { StringBuilder newString = new StringBuilder(); newString.Append(indexed.Value); newString[number] = WrittenChar[0]; newValue = FlagsHandler.CopyFlags(indexed, Context.CreateString(newString.ToString())); } else if (number == indexed.Value.Count()) { newValue = FlagsHandler.CopyFlags(indexed, Context.CreateString(indexed.Value + "" + WrittenChar[0].ToString())); } else { newValue = FlagsHandler.CopyFlags(indexed, Context.CreateString(indexed.Value + " " + WrittenChar[0].ToString())); } result.Add(newValue); } } if (!isConcrete) { result.Add(FlagsHandler.CopyFlags(indexed, Context.AnyStringValue)); } return(result); }
/// <summary> /// Perform simplification of memory entry /// In some cases resulting memory entry contains leas accurate information /// </summary> /// <param name="entry">Memory entry</param> /// <returns>simplified memory entry</returns> public IEnumerable <Value> Simplify(MemoryEntry entry) { foreach (var value in entry.PossibleValues) { value.Accept(this); } if (booleans.Count >= 2) { result.Add(context.AnyBooleanValue); } else { foreach (var boolean in booleans) { result.Add(boolean); } } if (strings.Count >= 2) { result.Add(FlagsHandler.CopyFlags(strings, context.AnyStringValue)); } else { foreach (var str in strings) { result.Add(str); } } if (containsInt) { if (minInt == maxInt) { result.Add(context.CreateInt(minInt)); } else { result.Add(context.CreateIntegerInterval(minInt, maxInt)); } } if (containsLong) { if (minLong == maxLong) { result.Add(context.CreateLong(minLong)); } else { result.Add(context.CreateLongintInterval(minLong, maxLong)); } } if (containsFloat) { if (minFloat == maxFloat) { result.Add(context.CreateDouble(minFloat)); } else { result.Add(context.CreateFloatInterval(minFloat, maxFloat)); } } return(result); }