From b858e0951f73de98e1f946ff9377801070a592e7 Mon Sep 17 00:00:00 2001 From: chrchr Date: Mon, 4 Oct 2021 21:12:22 +0200 Subject: [PATCH 1/4] Add test case --- test/testvalueflow.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index f8d417c9449..2875762e7d5 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -5587,6 +5587,20 @@ class TestValueFlow : public TestFixture { " return v;\n" "}\n"; ASSERT_EQUALS(true, tokenValues(code, "v [ 0 ] != 0 ) { }", ValueFlow::Value::ValueType::CONTAINER_SIZE).empty()); + + code = "int f(std::wsregex_token_iterator it) {\n" + " std::vector w{ it, {} };\n" + " int x = w.size();\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(false, testValueOfXKnown(code, 4U, 2)); + + //code = "bool f() {\n" + // " std::vector vec;\n" + // " auto it = vec.begin();\n" + // " return it == vec.begin();\n" + // "}\n"; + //ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "it"), 0)); } void valueFlowDynamicBufferSize() { From 5f25f794bb31e0786b91c4d78cf8f018f1da237f Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 5 Oct 2021 14:58:25 +0200 Subject: [PATCH 2/4] Fix astIsGenericChar(), add comments, test case --- lib/astutils.cpp | 2 +- lib/valueflow.cpp | 15 +++++++++------ test/testvalueflow.cpp | 20 +++++++------------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index a8eb38609e6..f70efeb47ba 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -205,7 +205,7 @@ bool astIsUnknownSignChar(const Token *tok) bool astIsGenericChar(const Token* tok) { - return tok && tok->valueType() && (tok->valueType()->type == ValueType::Type::CHAR || tok->valueType()->type == ValueType::Type::WCHAR_T); + return !astIsPointer(tok) && tok && tok->valueType() && (tok->valueType()->type == ValueType::Type::CHAR || tok->valueType()->type == ValueType::Type::WCHAR_T); } bool astIsIntegral(const Token *tok, bool unknown) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index d4b0065be5d..61714313180 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -6957,18 +6957,21 @@ static std::vector getInitListSize(const Token* tok, if (!args.empty() && container->stdStringLike) { if (astIsGenericChar(args[0])) // init list of chars return { makeContainerSizeValue(args.size(), known) }; - if (astIsIntegral(args[0], false)) { + if (astIsIntegral(args[0], false)) { // { count, 'c' } if (args.size() > 1) return {makeContainerSizeValue(args[0], known)}; } else if (astIsPointer(args[0])) { - // TODO: Try to read size of string literal - if (args.size() == 2 && astIsIntegral(args[1], false)) - return {makeContainerSizeValue(args[1], known)}; + // TODO: Try to read size of string literal { "abc" } + if (args.size() == 2 && astIsIntegral(args[1], false)) // { char*, count } + return {makeContainerSizeValue(args[1], known)}; + } else if (isIteratorPair(args)) { // { p, p + size } or { s.begin(), s.begin() + n } + return getContainerValues(args[0]); } else if (astIsContainer(args[0])) { - if (args.size() == 1) + if (args.size() == 1) // copy constructor { str } return getContainerValues(args[0]); - if (args.size() == 3) + if (args.size() == 3) // { str, pos, count } return {makeContainerSizeValue(args[2], known)}; + // TODO: { str, pos }, { ..., alloc } } return {}; } else if ((args.size() == 1 && astIsContainer(args[0]) && args[0]->valueType()->container == container) || diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 5b8dc124f39..d1318abfaa3 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -5126,6 +5126,13 @@ class TestValueFlow : public TestFixture { "}"; ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "s . size"), 3)); + code = "void f(const char* p) {\n" + " if (p == nullptr) return;\n" + " std::string s { p };\n" // size of s is unknown + " s.front();\n" + "}"; + ASSERT(tokenValues(code, "s . front").empty()); + code = "void f() {\n" " std::string s = { 'a', 'b', 'c' };\n" // size of s is 3 " s.size();\n" @@ -5614,19 +5621,6 @@ class TestValueFlow : public TestFixture { "}\n"; ASSERT_EQUALS(true, tokenValues(code, "v [ 0 ] != 0 ) { }", ValueFlow::Value::ValueType::CONTAINER_SIZE).empty()); - code = "int f(std::wsregex_token_iterator it) {\n" - " std::vector w{ it, {} };\n" - " int x = w.size();\n" - " return x;\n" - "}\n"; - ASSERT_EQUALS(false, testValueOfXKnown(code, 4U, 2)); - - //code = "bool f() {\n" - // " std::vector vec;\n" - // " auto it = vec.begin();\n" - // " return it == vec.begin();\n" - // "}\n"; - //ASSERT_EQUALS("", isKnownContainerSizeValue(tokenValues(code, "it"), 0)); } void valueFlowDynamicBufferSize() { From c57ca9ff2b169371766f6057e8b575e13efcdede Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 5 Oct 2021 15:03:06 +0200 Subject: [PATCH 3/4] Format --- test/testvalueflow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index d1318abfaa3..edd3577cd73 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -5620,7 +5620,6 @@ class TestValueFlow : public TestFixture { " return v;\n" "}\n"; ASSERT_EQUALS(true, tokenValues(code, "v [ 0 ] != 0 ) { }", ValueFlow::Value::ValueType::CONTAINER_SIZE).empty()); - } void valueFlowDynamicBufferSize() { From 596e68ab5e44b93121a958b27019687243f3b737 Mon Sep 17 00:00:00 2001 From: chrchr Date: Tue, 5 Oct 2021 16:33:40 +0200 Subject: [PATCH 4/4] Undo unrelated change --- lib/valueflow.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 61714313180..c37d1b69900 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -6963,9 +6963,7 @@ static std::vector getInitListSize(const Token* tok, } else if (astIsPointer(args[0])) { // TODO: Try to read size of string literal { "abc" } if (args.size() == 2 && astIsIntegral(args[1], false)) // { char*, count } - return {makeContainerSizeValue(args[1], known)}; - } else if (isIteratorPair(args)) { // { p, p + size } or { s.begin(), s.begin() + n } - return getContainerValues(args[0]); + return {makeContainerSizeValue(args[1], known)}; } else if (astIsContainer(args[0])) { if (args.size() == 1) // copy constructor { str } return getContainerValues(args[0]);