/// <inheritdoc /> public override void VisitUndefinedValue(UndefinedValue value) { switch (operation) { case Operations.Equal: case Operations.Identical: case Operations.LessThan: case Operations.LessThanOrEqual: case Operations.And: result = OutSet.CreateBool(false); break; case Operations.NotEqual: case Operations.NotIdentical: case Operations.GreaterThan: case Operations.GreaterThanOrEqual: case Operations.Or: case Operations.Xor: result = OutSet.CreateBool(true); break; default: switch (operation) { case Operations.Mul: case Operations.BitAnd: SetWarning("Object cannot be converted to integer", AnalysisWarningCause.OBJECT_CONVERTED_TO_INTEGER); result = OutSet.CreateInt(0); break; case Operations.Add: case Operations.Sub: case Operations.BitOr: case Operations.BitXor: case Operations.ShiftLeft: case Operations.ShiftRight: SetWarning("Object cannot be converted to integer", AnalysisWarningCause.OBJECT_CONVERTED_TO_INTEGER); result = OutSet.AnyIntegerValue; break; case Operations.Div: SetWarning("Object cannot be converted to integer", AnalysisWarningCause.OBJECT_CONVERTED_TO_INTEGER); result = ArithmeticOperation.DivisionByNull(flow); break; case Operations.Mod: SetWarning("Object cannot be converted to integer by modulo operation", AnalysisWarningCause.OBJECT_CONVERTED_TO_INTEGER); result = ModuloOperation.ModuloByNull(flow); break; default: base.VisitUndefinedValue(value); break; } break; } }
/// <inheritdoc /> public override void VisitStringValue(StringValue value) { switch (operation) { case Operations.Identical: result = OutSet.CreateBool(string.Equals(leftOperand.Value, value.Value, StringComparison.Ordinal)); break; case Operations.NotIdentical: result = OutSet.CreateBool(!string.Equals(leftOperand.Value, value.Value, StringComparison.Ordinal)); break; case Operations.Mod: result = ModuloOperation.Modulo(flow, leftOperand.Value, value.Value); break; case Operations.BitAnd: case Operations.BitOr: case Operations.BitXor: // Bit operations are defined for every character, not for the entire string // TODO: PHP string is stored as array of bytes, but printed in UTF8 encoding result = OutSet.AnyStringValue; break; default: result = LogicalOperation.Logical(OutSet, operation, TypeConversion.ToBoolean(leftOperand.Value), TypeConversion.ToBoolean(value.Value)); if (result != null) { break; } int leftInteger; double leftFloat; bool isLeftInteger; bool isLeftHexadecimal; var isLeftSuccessful = TypeConversion.TryConvertToNumber(leftOperand.Value, true, out leftInteger, out leftFloat, out isLeftInteger, out isLeftHexadecimal); int rightInteger; double rightFloat; bool isRightInteger; bool isRightHexadecimal; var isRightSuccessful = TypeConversion.TryConvertToNumber(value.Value, true, out rightInteger, out rightFloat, out isRightInteger, out isRightHexadecimal); // If both strings are convertible to number, they are conpared as numbers result = (isLeftSuccessful && isRightSuccessful) ? ((isLeftInteger && isRightInteger) ? Comparison.Compare(OutSet, operation, leftInteger, rightInteger) : Comparison.Compare(OutSet, operation, leftFloat, rightFloat)) : Comparison.Compare(OutSet, operation, leftOperand.Value, value.Value); if (result != null) { break; } result = (isLeftInteger && isRightInteger) ? ArithmeticOperation.Arithmetic(flow, operation, leftInteger, rightInteger) : ArithmeticOperation.Arithmetic(flow, operation, leftFloat, rightFloat); if (result != null) { break; } // If string has hexadecimal format, the first zero is recognized. if (isLeftHexadecimal) { leftInteger = 0; } if (isRightHexadecimal) { rightInteger = 0; } // Only shifting operations can happen if ((isLeftInteger || (isLeftSuccessful && TypeConversion.TryConvertToInteger(leftFloat, out leftInteger))) && (isRightInteger || (isRightSuccessful && TypeConversion.TryConvertToInteger(rightFloat, out rightInteger)))) { result = BitwiseOperation.Bitwise(OutSet, operation, leftInteger, rightInteger); if (result != null) { break; } } else { // If at least one operand can not be recognized, result can be any integer value. result = BitwiseOperation.Bitwise(OutSet, operation); if (result != null) { break; } } base.VisitStringValue(value); break; } }
/// <inheritdoc /> public override void VisitBooleanValue(BooleanValue value) { switch (operation) { case Operations.Identical: result = OutSet.CreateBool(false); break; case Operations.NotIdentical: result = OutSet.CreateBool(true); break; default: var leftBoolean = TypeConversion.ToBoolean(leftOperand.Value); result = Comparison.Compare(OutSet, operation, leftBoolean, value.Value); if (result != null) { break; } result = LogicalOperation.Logical(OutSet, operation, leftBoolean, value.Value); if (result != null) { break; } int integerValue; double floatValue; bool isInteger; bool isHexadecimal; var isSuccessful = TypeConversion.TryConvertToNumber(leftOperand.Value, true, out integerValue, out floatValue, out isInteger, out isHexadecimal); var rightInteger = TypeConversion.ToInteger(value.Value); result = isInteger ? ArithmeticOperation.Arithmetic(flow, operation, integerValue, rightInteger) : ArithmeticOperation.Arithmetic(flow, operation, floatValue, rightInteger); if (result != null) { break; } // If string has hexadecimal format, the first zero is recognized. if (isHexadecimal) { integerValue = 0; } if (isInteger || (isSuccessful && TypeConversion.TryConvertToInteger(floatValue, out integerValue))) { result = BitwiseOperation.Bitwise(OutSet, operation, integerValue, rightInteger); if (result != null) { break; } } else { // If the left operand can not be recognized, result can be any integer value. result = BitwiseOperation.Bitwise(OutSet, operation); if (result != null) { break; } } base.VisitBooleanValue(value); break; } }
/// <inheritdoc /> public override void VisitStringValue(StringValue value) { int integerValue; double floatValue; bool isInteger; switch (operation) { case Operations.Plus: TypeConversion.TryConvertToNumber(value.Value, true, out integerValue, out floatValue, out isInteger); if (isInteger) { result = OutSet.CreateInt(integerValue); } else { result = OutSet.CreateDouble(floatValue); } break; case Operations.Minus: TypeConversion.TryConvertToNumber(value.Value, true, out integerValue, out floatValue, out isInteger); if (isInteger) { if ((integerValue == 0) || ((-integerValue) != 0)) { result = OutSet.CreateInt(-integerValue); } else { // <seealso cref="UnaryOperationEvaluator.VisitIntegerValue" /> result = OutSet.CreateDouble(-TypeConversion.ToFloat(integerValue)); } } else { result = OutSet.CreateDouble(floatValue); } break; case Operations.LogicNegation: result = OutSet.CreateBool(!TypeConversion.ToBoolean(value.Value)); break; case Operations.BitNegation: // Bit negation is defined for every character, not for the entire string // TODO: Implement. PHP string is stored as array of bytes, but printed in UTF8 encoding result = OutSet.AnyStringValue; break; case Operations.Int32Cast: result = TypeConversion.ToInteger(OutSet, value); break; case Operations.FloatCast: case Operations.DoubleCast: result = TypeConversion.ToFloat(Snapshot, value); break; default: base.VisitStringValue(value); break; } }