| 917 | } |
| 918 | |
| 919 | static bool getExpressionRange(const Token* expr, MathLib::bigint* minvalue, MathLib::bigint* maxvalue) |
| 920 | { |
| 921 | if (const ValueFlow::Value* v = expr->getKnownValue(ValueFlow::Value::ValueType::INT)) { |
| 922 | if (minvalue) |
| 923 | *minvalue = v->intvalue; |
| 924 | if (maxvalue) |
| 925 | *maxvalue = v->intvalue; |
| 926 | return true; |
| 927 | } |
| 928 | |
| 929 | if (expr->str() == "&" && expr->astOperand1() && expr->astOperand2()) { |
| 930 | MathLib::bigint vals[4]; |
| 931 | const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]); |
| 932 | const bool rhsHasKnownRange = getExpressionRange(expr->astOperand2(), &vals[2], &vals[3]); |
| 933 | if (!lhsHasKnownRange && !rhsHasKnownRange) |
| 934 | return false; |
| 935 | if (!lhsHasKnownRange || !rhsHasKnownRange) { |
| 936 | if (minvalue) |
| 937 | *minvalue = lhsHasKnownRange ? vals[0] : vals[2]; |
| 938 | if (maxvalue) |
| 939 | *maxvalue = lhsHasKnownRange ? vals[1] : vals[3]; |
| 940 | } else { |
| 941 | if (minvalue) |
| 942 | *minvalue = vals[0] & vals[2]; |
| 943 | if (maxvalue) |
| 944 | *maxvalue = vals[1] & vals[3]; |
| 945 | } |
| 946 | return true; |
| 947 | } |
| 948 | |
| 949 | if (expr->str() == "%" && expr->astOperand1() && expr->astOperand2()) { |
| 950 | MathLib::bigint vals[4]; |
| 951 | if (!getExpressionRange(expr->astOperand2(), &vals[2], &vals[3])) |
| 952 | return false; |
| 953 | if (vals[2] <= 0) |
| 954 | return false; |
| 955 | const bool lhsHasKnownRange = getExpressionRange(expr->astOperand1(), &vals[0], &vals[1]); |
| 956 | if (lhsHasKnownRange && vals[0] < 0) |
| 957 | return false; |
| 958 | // If lhs has unknown value, it must be unsigned |
| 959 | if (!lhsHasKnownRange && |
| 960 | (!expr->astOperand1()->valueType() || expr->astOperand1()->valueType()->sign != ValueType::Sign::UNSIGNED)) |
| 961 | return false; |
| 962 | if (minvalue) |
| 963 | *minvalue = 0; |
| 964 | if (maxvalue) |
| 965 | *maxvalue = vals[3] - 1; |
| 966 | return true; |
| 967 | } |
| 968 | |
| 969 | return false; |
| 970 | } |
| 971 | |
| 972 | static void valueFlowRightShift(TokenList& tokenList, const Settings& settings) |
| 973 | { |
no test coverage detected