Skip to content

Commit 10f8b24

Browse files
authored
Fix potential invalid memory access in StringSplitter (#2996)
1 parent fed6275 commit 10f8b24

2 files changed

Lines changed: 53 additions & 8 deletions

File tree

src/butil/string_splitter_inl.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ void StringSplitter::init() {
4747
// Find the starting _head and _tail.
4848
if (__builtin_expect(_head != NULL, 1)) {
4949
if (_empty_field_action == SKIP_EMPTY_FIELD) {
50-
for (; _sep == *_head && not_end(_head); ++_head) {}
50+
for (; not_end(_head) && *_head == _sep; ++_head) {}
5151
}
52-
for (_tail = _head; *_tail != _sep && not_end(_tail); ++_tail) {}
52+
for (_tail = _head; not_end(_tail) && *_tail != _sep; ++_tail) {}
5353
} else {
5454
_tail = NULL;
5555
}
@@ -60,11 +60,11 @@ StringSplitter& StringSplitter::operator++() {
6060
if (not_end(_tail)) {
6161
++_tail;
6262
if (_empty_field_action == SKIP_EMPTY_FIELD) {
63-
for (; _sep == *_tail && not_end(_tail); ++_tail) {}
63+
for (; not_end(_tail) && *_tail == _sep; ++_tail) {}
6464
}
6565
}
6666
_head = _tail;
67-
for (; *_tail != _sep && not_end(_tail); ++_tail) {}
67+
for (; not_end(_tail) && *_tail != _sep; ++_tail) {}
6868
}
6969
return *this;
7070
}
@@ -189,9 +189,9 @@ StringMultiSplitter::StringMultiSplitter (
189189
void StringMultiSplitter::init() {
190190
if (__builtin_expect(_head != NULL, 1)) {
191191
if (_empty_field_action == SKIP_EMPTY_FIELD) {
192-
for (; is_sep(*_head) && not_end(_head); ++_head) {}
192+
for (; not_end(_head) && is_sep(*_head); ++_head) {}
193193
}
194-
for (_tail = _head; !is_sep(*_tail) && not_end(_tail); ++_tail) {}
194+
for (_tail = _head; not_end(_tail) && !is_sep(*_tail); ++_tail) {}
195195
} else {
196196
_tail = NULL;
197197
}
@@ -202,11 +202,11 @@ StringMultiSplitter& StringMultiSplitter::operator++() {
202202
if (not_end(_tail)) {
203203
++_tail;
204204
if (_empty_field_action == SKIP_EMPTY_FIELD) {
205-
for (; is_sep(*_tail) && not_end(_tail); ++_tail) {}
205+
for (; not_end(_tail) && is_sep(*_tail); ++_tail) {}
206206
}
207207
}
208208
_head = _tail;
209-
for (; !is_sep(*_tail) && not_end(_tail); ++_tail) {}
209+
for (; not_end(_tail) && !is_sep(*_tail); ++_tail) {}
210210
}
211211
return *this;
212212
}

test/string_splitter_unittest.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,51 @@ TEST_F(StringSplitterTest, split_limit_len) {
354354
ASSERT_FALSE(ss3);
355355
}
356356

357+
TEST_F(StringSplitterTest, non_null_terminated_string) {
358+
const char str[] = " a non null terminated string ";
359+
const size_t len = strlen(str);
360+
char* buf = new char[len];
361+
memcpy(buf, str, len);
362+
363+
butil::StringSplitter ss(buf, buf + len, ' ');
364+
365+
// "a"
366+
ASSERT_TRUE(ss != NULL);
367+
ASSERT_EQ(1ul, ss.length());
368+
ASSERT_EQ(ss.field(), buf + 2);
369+
370+
// "non"
371+
++ss;
372+
ASSERT_TRUE(ss != NULL);
373+
ASSERT_EQ(3ul, ss.length());
374+
ASSERT_EQ(ss.field(), buf + 4);
375+
376+
// "null"
377+
++ss;
378+
ASSERT_TRUE(ss != NULL);
379+
ASSERT_EQ(4ul, ss.length());
380+
ASSERT_EQ(ss.field(), buf + 9);
381+
382+
// "terminated"
383+
++ss;
384+
ASSERT_TRUE(ss != NULL);
385+
ASSERT_EQ(10ul, ss.length());
386+
ASSERT_EQ(ss.field(), buf + 16);
387+
388+
// "string"
389+
++ss;
390+
ASSERT_TRUE(ss != NULL);
391+
ASSERT_EQ(6ul, ss.length());
392+
ASSERT_EQ(ss.field(), buf + 28);
393+
394+
++ss;
395+
ASSERT_FALSE(ss);
396+
ASSERT_EQ(0ul, ss.length());
397+
ASSERT_EQ(ss.field(), buf + len);
398+
399+
delete[] buf;
400+
}
401+
357402
TEST_F(StringSplitterTest, key_value_pairs_splitter_sanity) {
358403
std::string kvstr = "key1=value1&&&key2=value2&key3=value3&===&key4=&=&=value5";
359404
for (int i = 0 ; i < 3; ++i) {

0 commit comments

Comments
 (0)