diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 7a06f66f644..dbc16f2d8ac 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2023,7 +2023,7 @@ void CheckOther::checkCharVariable() if (!tok->variable()->isArray() && !tok->variable()->isPointer()) continue; const Token *index = tok->next()->astOperand2(); - if (warning && tok->variable()->isArray() && astIsSignedChar(index) && index->getValueGE(0x80, *mSettings)) + if (warning && astIsSignedChar(index) && index->getValueLE(-1, *mSettings)) signedCharArrayIndexError(tok); if (portability && astIsUnknownSignChar(index) && index->getValueGE(0x80, *mSettings)) unknownSignCharArrayIndexError(tok); diff --git a/lib/token.cpp b/lib/token.cpp index 98f79b4bb1d..400f07228fb 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1922,6 +1922,7 @@ const ValueFlow::Value * Token::getValueLE(const MathLib::bigint val, const Sett { if (!mImpl->mValues) return nullptr; + // TODO: assert the given value is actually possible - i.e. 0x80 for a signed char is not possible return ValueFlow::findValue(*mImpl->mValues, settings, [&](const ValueFlow::Value& v) { return !v.isImpossible() && v.isIntValue() && v.intvalue <= val; }); @@ -1931,6 +1932,7 @@ const ValueFlow::Value * Token::getValueGE(const MathLib::bigint val, const Sett { if (!mImpl->mValues) return nullptr; + // TODO: assert the given value is actually possible - i.e. 0x80 for a signed char is not possible return ValueFlow::findValue(*mImpl->mValues, settings, [&](const ValueFlow::Value& v) { return !v.isImpossible() && v.isIntValue() && v.intvalue >= val; }); @@ -1940,6 +1942,7 @@ const ValueFlow::Value * Token::getValueNE(MathLib::bigint val) const { if (!mImpl->mValues) return nullptr; + // TODO: assert the given value is actually possible - i.e. 0x80 for a signed char is not possible const auto it = std::find_if(mImpl->mValues->cbegin(), mImpl->mValues->cend(), [=](const ValueFlow::Value& value) { return value.isIntValue() && !value.isImpossible() && value.intvalue != val; }); diff --git a/test/testcharvar.cpp b/test/testcharvar.cpp index 624efcff539..f2fd4b3653a 100644 --- a/test/testcharvar.cpp +++ b/test/testcharvar.cpp @@ -60,6 +60,14 @@ class TestCharVar : public TestFixture { "}"); ASSERT_EQUALS("", errout_str()); + check("int buf[256];\n" + "void foo()\n" + "{\n" + " signed char ch = 0x80;\n" + " buf[ch] = 0;\n" + "}"); + ASSERT_EQUALS("[test.cpp:5:5]: (warning) Signed 'char' type used as array index. [signedCharArrayIndex]\n", errout_str()); + check("int buf[256];\n" "void foo()\n" "{\n" @@ -71,7 +79,7 @@ class TestCharVar : public TestFixture { check("int buf[256];\n" "void foo()\n" "{\n" - " char ch = 0;\n" + " unsigned char ch = 0;\n" " buf[ch] = 0;\n" "}"); ASSERT_EQUALS("", errout_str()); @@ -87,10 +95,17 @@ class TestCharVar : public TestFixture { check("int buf[256];\n" "void foo()\n" "{\n" - " char ch = 0x80;\n" + " char ch = 0;\n" " buf[ch] = 0;\n" "}"); - ASSERT_EQUALS("[test.cpp:5:5]: (portability) 'char' type used as array index. [unknownSignCharArrayIndex]\n", errout_str()); + ASSERT_EQUALS("", errout_str()); + + check("int buf[256];\n" + "void foo(unsigned char ch)\n" + "{\n" + " buf[ch] = 0;\n" + "}"); + ASSERT_EQUALS("", errout_str()); check("int buf[256];\n" "void foo(signed char ch)\n" @@ -106,6 +121,20 @@ class TestCharVar : public TestFixture { "}"); ASSERT_EQUALS("", errout_str()); + check("void foo(char* buf)\n" + "{\n" + " unsigned char ch = 0x80;" + " buf[ch] = 0;\n" + "}"); + ASSERT_EQUALS("", errout_str()); + + check("void foo(char* buf)\n" + "{\n" + " signed char ch = 0x80;" + " buf[ch] = 0;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3:31]: (warning) Signed 'char' type used as array index. [signedCharArrayIndex]\n", errout_str()); + check("void foo(char* buf)\n" "{\n" " char ch = 0x80;" @@ -113,6 +142,20 @@ class TestCharVar : public TestFixture { "}"); ASSERT_EQUALS("[test.cpp:3:24]: (portability) 'char' type used as array index. [unknownSignCharArrayIndex]\n", errout_str()); + check("void foo(char* buf)\n" + "{\n" + " unsigned char ch = 0;" + " buf[ch] = 0;\n" + "}"); + ASSERT_EQUALS("", errout_str()); + + check("void foo(char* buf)\n" + "{\n" + " signed char ch = 0;" + " buf[ch] = 0;\n" + "}"); + ASSERT_EQUALS("", errout_str()); + check("void foo(char* buf)\n" "{\n" " char ch = 0;" @@ -126,6 +169,18 @@ class TestCharVar : public TestFixture { "}"); ASSERT_EQUALS("", errout_str()); + check("void foo(char* buf, unsigned char ch)\n" + "{\n" + " buf[ch] = 0;\n" + "}"); + ASSERT_EQUALS("", errout_str()); + + check("void foo(char* buf, signed char ch)\n" + "{\n" + " buf[ch] = 0;\n" + "}"); + ASSERT_EQUALS("", errout_str()); + check("void foo(char* buf, char ch)\n" "{\n" " buf[ch] = 0;\n" @@ -135,7 +190,7 @@ class TestCharVar : public TestFixture { check("int flags[256];\n" "void foo(const char* str)\n" "{\n" - " flags[*str] = 0;\n" + " flags[(signed char)*str] = 0;\n" "}"); ASSERT_EQUALS("", errout_str()); @@ -146,6 +201,13 @@ class TestCharVar : public TestFixture { "}"); ASSERT_EQUALS("", errout_str()); + check("int flags[256];\n" + "void foo(const char* str)\n" + "{\n" + " flags[*str] = 0;\n" + "}"); + ASSERT_EQUALS("", errout_str()); + check("void foo(const char str[])\n" "{\n" " map[str] = 0;\n"