Skip to content

Commit d1bfae9

Browse files
authored
fixed handling of incomplete char/string literals in isPrefixStringCharLiteral() - also optimized it a bit (danmar#4541)
* fixed handling of incomplete char/string literals in `isPrefixStringCharLiteral()` - also optimized it a bit / added tests for `isStringLiteral()` and `isCharLiteral()` * utils.h: early out in `isStringCharLiteral()` to avoid the loop
1 parent c5a2264 commit d1bfae9

File tree

2 files changed

+129
-3
lines changed

2 files changed

+129
-3
lines changed

lib/utils.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,31 @@ bool endsWith(const std::string& str, const char (&end)[N])
8989

9090
inline static bool isPrefixStringCharLiteral(const std::string &str, char q, const std::string& p)
9191
{
92+
// str must be at least the prefix plus the start and end quote
93+
if (str.length() < p.length() + 2)
94+
return false;
95+
96+
// check for end quote
9297
if (!endsWith(str, q))
9398
return false;
94-
if ((str.length() + 1) > p.length() && (str.compare(0, p.size() + 1, p + q) == 0))
95-
return true;
96-
return false;
99+
100+
// check for start quote
101+
if (str[p.size()] != q)
102+
return false;
103+
104+
// check for prefix
105+
if (str.compare(0, p.size(), p) != 0)
106+
return false;
107+
108+
return true;
97109
}
98110

99111
inline static bool isStringCharLiteral(const std::string &str, char q)
100112
{
113+
// early out to avoid the loop
114+
if (!endsWith(str, q))
115+
return false;
116+
101117
static const std::array<std::string, 5> suffixes{"", "u8", "u", "U", "L"};
102118
for (const std::string & p: suffixes) {
103119
if (isPrefixStringCharLiteral(str, q, p))

test/testutils.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class TestUtils : public TestFixture {
3030
void run() override {
3131
TEST_CASE(isValidGlobPattern);
3232
TEST_CASE(matchglob);
33+
TEST_CASE(isStringLiteral);
34+
TEST_CASE(isCharLiteral);
3335
}
3436

3537
void isValidGlobPattern() const {
@@ -68,6 +70,114 @@ class TestUtils : public TestFixture {
6870
ASSERT_EQUALS(true, ::matchglob("?y?", "xyz"));
6971
ASSERT_EQUALS(true, ::matchglob("?/?/?", "x/y/z"));
7072
}
73+
74+
void isStringLiteral() const {
75+
// empty
76+
ASSERT_EQUALS(false, ::isStringLiteral(""));
77+
78+
// no literals
79+
ASSERT_EQUALS(false, ::isStringLiteral("u8"));
80+
ASSERT_EQUALS(false, ::isStringLiteral("u"));
81+
ASSERT_EQUALS(false, ::isStringLiteral("U"));
82+
ASSERT_EQUALS(false, ::isStringLiteral("L"));
83+
84+
// incomplete string literals
85+
ASSERT_EQUALS(false, ::isStringLiteral("\""));
86+
ASSERT_EQUALS(false, ::isStringLiteral("u8\""));
87+
ASSERT_EQUALS(false, ::isStringLiteral("u\""));
88+
ASSERT_EQUALS(false, ::isStringLiteral("U\""));
89+
ASSERT_EQUALS(false, ::isStringLiteral("L\""));
90+
91+
// valid string literals
92+
ASSERT_EQUALS(true, ::isStringLiteral("\"\""));
93+
ASSERT_EQUALS(true, ::isStringLiteral("u8\"\""));
94+
ASSERT_EQUALS(true, ::isStringLiteral("u\"\""));
95+
ASSERT_EQUALS(true, ::isStringLiteral("U\"\""));
96+
ASSERT_EQUALS(true, ::isStringLiteral("L\"\""));
97+
ASSERT_EQUALS(true, ::isStringLiteral("\"t\""));
98+
ASSERT_EQUALS(true, ::isStringLiteral("u8\"t\""));
99+
ASSERT_EQUALS(true, ::isStringLiteral("u\"t\""));
100+
ASSERT_EQUALS(true, ::isStringLiteral("U\"t\""));
101+
ASSERT_EQUALS(true, ::isStringLiteral("L\"t\""));
102+
ASSERT_EQUALS(true, ::isStringLiteral("\"test\""));
103+
ASSERT_EQUALS(true, ::isStringLiteral("u8\"test\""));
104+
ASSERT_EQUALS(true, ::isStringLiteral("u\"test\""));
105+
ASSERT_EQUALS(true, ::isStringLiteral("U\"test\""));
106+
ASSERT_EQUALS(true, ::isStringLiteral("L\"test\""));
107+
108+
// incomplete char literals
109+
ASSERT_EQUALS(false, ::isStringLiteral("'"));
110+
ASSERT_EQUALS(false, ::isStringLiteral("u8'"));
111+
ASSERT_EQUALS(false, ::isStringLiteral("u'"));
112+
ASSERT_EQUALS(false, ::isStringLiteral("U'"));
113+
ASSERT_EQUALS(false, ::isStringLiteral("L'"));
114+
115+
// valid char literals
116+
ASSERT_EQUALS(false, ::isStringLiteral("'t'"));
117+
ASSERT_EQUALS(false, ::isStringLiteral("u8't'"));
118+
ASSERT_EQUALS(false, ::isStringLiteral("u't'"));
119+
ASSERT_EQUALS(false, ::isStringLiteral("U't'"));
120+
ASSERT_EQUALS(false, ::isStringLiteral("L't'"));
121+
ASSERT_EQUALS(false, ::isStringLiteral("'test'"));
122+
ASSERT_EQUALS(false, ::isStringLiteral("u8'test'"));
123+
ASSERT_EQUALS(false, ::isStringLiteral("u'test'"));
124+
ASSERT_EQUALS(false, ::isStringLiteral("U'test'"));
125+
ASSERT_EQUALS(false, ::isStringLiteral("L'test'"));
126+
}
127+
128+
void isCharLiteral() const {
129+
// empty
130+
ASSERT_EQUALS(false, ::isCharLiteral(""));
131+
132+
// no literals
133+
ASSERT_EQUALS(false, ::isCharLiteral("u8"));
134+
ASSERT_EQUALS(false, ::isCharLiteral("u"));
135+
ASSERT_EQUALS(false, ::isCharLiteral("U"));
136+
ASSERT_EQUALS(false, ::isCharLiteral("L"));
137+
138+
// incomplete string literals
139+
ASSERT_EQUALS(false, ::isCharLiteral("\""));
140+
ASSERT_EQUALS(false, ::isCharLiteral("u8\""));
141+
ASSERT_EQUALS(false, ::isCharLiteral("u\""));
142+
ASSERT_EQUALS(false, ::isCharLiteral("U\""));
143+
ASSERT_EQUALS(false, ::isCharLiteral("L\""));
144+
145+
// valid string literals
146+
ASSERT_EQUALS(false, ::isCharLiteral("\"\""));
147+
ASSERT_EQUALS(false, ::isCharLiteral("u8\"\""));
148+
ASSERT_EQUALS(false, ::isCharLiteral("u\"\""));
149+
ASSERT_EQUALS(false, ::isCharLiteral("U\"\""));
150+
ASSERT_EQUALS(false, ::isCharLiteral("L\"\""));
151+
ASSERT_EQUALS(false, ::isCharLiteral("\"t\""));
152+
ASSERT_EQUALS(false, ::isCharLiteral("u8\"t\""));
153+
ASSERT_EQUALS(false, ::isCharLiteral("u\"t\""));
154+
ASSERT_EQUALS(false, ::isCharLiteral("U\"t\""));
155+
ASSERT_EQUALS(false, ::isCharLiteral("L\"t\""));
156+
ASSERT_EQUALS(false, ::isCharLiteral("\"test\""));
157+
ASSERT_EQUALS(false, ::isCharLiteral("u8\"test\""));
158+
ASSERT_EQUALS(false, ::isCharLiteral("u\"test\""));
159+
ASSERT_EQUALS(false, ::isCharLiteral("U\"test\""));
160+
ASSERT_EQUALS(false, ::isCharLiteral("L\"test\""));
161+
162+
// incomplete char literals
163+
ASSERT_EQUALS(false, ::isCharLiteral("'"));
164+
ASSERT_EQUALS(false, ::isCharLiteral("u8'"));
165+
ASSERT_EQUALS(false, ::isCharLiteral("u'"));
166+
ASSERT_EQUALS(false, ::isCharLiteral("U'"));
167+
ASSERT_EQUALS(false, ::isCharLiteral("L'"));
168+
169+
// valid char literals
170+
ASSERT_EQUALS(true, ::isCharLiteral("'t'"));
171+
ASSERT_EQUALS(true, ::isCharLiteral("u8't'"));
172+
ASSERT_EQUALS(true, ::isCharLiteral("u't'"));
173+
ASSERT_EQUALS(true, ::isCharLiteral("U't'"));
174+
ASSERT_EQUALS(true, ::isCharLiteral("L't'"));
175+
ASSERT_EQUALS(true, ::isCharLiteral("'test'"));
176+
ASSERT_EQUALS(true, ::isCharLiteral("u8'test'"));
177+
ASSERT_EQUALS(true, ::isCharLiteral("u'test'"));
178+
ASSERT_EQUALS(true, ::isCharLiteral("U'test'"));
179+
ASSERT_EQUALS(true, ::isCharLiteral("L'test'"));
180+
}
71181
};
72182

73183
REGISTER_TEST(TestUtils)

0 commit comments

Comments
 (0)