Unverified Commit 8528ff22 authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #1166

Fix unsafe use of strncmp
parents 0221960c 97f30de1
......@@ -28,8 +28,9 @@ elif [ $# = 2 ]; then
if [ "$1" = 'test' ] && [ -d "$2" ]; then
Mode='test'
BuildDir="$2"
elif [ "$1" = 'assert' ] && [ "$2" = 'LeakSanitizer' ]; then
elif [ "$1" = 'assert' ]; then
Mode='assert'
What="$2"
else
usage
fi
......@@ -85,10 +86,37 @@ runLeakSanitizerCheck() {
fi
}
runUBSanitizerCheck() {
UBSanCheckStr="
int main(int argc, char**) {
int k = 0x7fffffff;
k += argc;
return 0;
}
"
echo "${UBSanCheckStr}" > UBSanCheck.cpp
c++ UBSanCheck.cpp -o UBSanCheck -fsanitize=undefined -fno-omit-frame-pointer
out=`./UBSanCheck 2>&1 | grep -o 'signed integer overflow'`
if [ -z "$out" ]; then
echo "unable to detected undefined behavior on this platform!"
return 1
fi
}
if [ "$Mode" = 'build' ]; then
runBuild
elif [ "$Mode" = 'test' ]; then
runTest
else
runLeakSanitizerCheck
case "$What" in
LeakSanitizer)
runLeakSanitizerCheck
;;
UBSanitizer)
runUBSanitizerCheck
;;
*)
echo "unrecognized tag: $What!"
return 1
esac
fi
......@@ -48,6 +48,7 @@ is based on [Keep a Changelog](https://keepachangelog.com).
console output.
- Fix memory leaks when deserializing URIs and when detaching the content of
messages (#1160).
- Fix undefined behavior in `string_view::compare` (#1164).
## [0.18.0-rc.1] - 2020-09-09
......
......@@ -93,13 +93,18 @@ config = [
'ASAN_OPTIONS=detect_leaks=1',
],
]],
// One extra debug build with static libraries.
['debian-10', [
// One extra debug build with static libraries and UBSanitizer.
['fedora-32', [
numCores: 4,
tags: ['docker'],
tags: ['docker', 'UBSanitizer'],
builds: ['debug'],
extraBuildFlags: [
'BUILD_SHARED_LIBS:BOOL=OFF',
'CAF_SANITIZERS:STRING=address,undefined',
],
extraBuildEnv: [
'CXXFLAGS=-fno-sanitize-recover=undefined',
'LDFLAGS=-fno-sanitize-recover=undefined',
],
]],
// Other UNIX systems.
......
......@@ -102,16 +102,18 @@ string_view string_view::substr(size_type pos, size_type n) const noexcept {
}
int string_view::compare(string_view str) const noexcept {
auto s0 = size();
auto s1 = str.size();
auto fallback = [](int x, int y) {
return x == 0 ? y : x;
};
if (s0 == s1)
return strncmp(data(), str.data(), s0);
else if (s0 < s1)
return fallback(strncmp(data(), str.data(), s0), -1);
return fallback(strncmp(data(), str.data(), s1), 1);
// TODO: use lexicographical_compare_three_way when switching to C++20
auto i0 = begin();
auto e0 = end();
auto i1 = str.begin();
auto e1 = str.end();
while (i0 != e0 && i1 != e1)
if (auto diff = *i0++ - *i1++; diff != 0)
return diff;
if (i0 == e0)
return i1 != e1 ? -1 : 0;
else
return i1 == e1 ? 1 : 0;
}
int string_view::compare(size_type pos1, size_type n1,
......
......@@ -23,6 +23,7 @@
#include "core-test.hpp"
using namespace caf;
using namespace caf::literals;
CAF_TEST(default construction) {
string_view x;
......@@ -34,7 +35,7 @@ CAF_TEST(default construction) {
}
CAF_TEST(cstring conversion) {
string_view x = "abc";
auto x = "abc"_sv;
CAF_CHECK_EQUAL(x.size(), 3u);
CAF_CHECK_EQUAL(x[0], 'a');
CAF_CHECK_EQUAL(x[1], 'b');
......@@ -50,14 +51,12 @@ CAF_TEST(string conversion) {
string_view y;
y = x;
CAF_CHECK_EQUAL(x, y);
auto f = [&](string_view z) {
CAF_CHECK_EQUAL(x, z);
};
auto f = [&](string_view z) { CAF_CHECK_EQUAL(x, z); };
f(x);
}
CAF_TEST(substrings) {
string_view x = "abcdefghi";
auto x = "abcdefghi"_sv;
CAF_CHECK(x.remove_prefix(3), "defghi");
CAF_CHECK(x.remove_suffix(3), "abcdef");
CAF_CHECK(x.substr(3, 3), "def");
......@@ -69,9 +68,9 @@ CAF_TEST(substrings) {
CAF_TEST(compare) {
// testees
string_view x = "abc";
string_view y = "bcd";
string_view z = "cde";
auto x = "abc"_sv;
auto y = "bcd"_sv;
auto z = "cde"_sv;
// x.compare full strings
CAF_CHECK(x.compare("abc") == 0);
CAF_CHECK(x.compare(y) < 0);
......@@ -88,14 +87,15 @@ CAF_TEST(compare) {
CAF_CHECK(x.compare(0, 3, "abc") == 0);
CAF_CHECK(x.compare(1, 2, y, 0, 2) == 0);
CAF_CHECK(x.compare(2, 1, z, 0, 1) == 0);
CAF_CHECK(x.compare(2, 1, z, 0, 1) == 0);
// make sure substrings aren't equal
CAF_CHECK(string_view("a/") != string_view("a/b"));
CAF_CHECK("a/"_sv != "a/b"_sv);
CAF_CHECK(z.compare("cdef"_sv) < 0);
CAF_CHECK("cdef"_sv.compare(z) > 0);
}
CAF_TEST(copy) {
char buf[10];
string_view str = "hello";
auto str = "hello"_sv;
auto n = str.copy(buf, str.size());
CAF_CHECK_EQUAL(n, 5u);
buf[n] = '\0';
......@@ -109,7 +109,7 @@ CAF_TEST(copy) {
CAF_TEST(find) {
// Check whether string_view behaves exactly like std::string.
string_view x = "abcdef";
auto x = "abcdef"_sv;
std::string y = "abcdef";
CAF_CHECK_EQUAL(x.find('a'), y.find('a'));
CAF_CHECK_EQUAL(x.find('b'), y.find('b'));
......@@ -126,7 +126,7 @@ CAF_TEST(find) {
CAF_TEST(rfind) {
// Check whether string_view behaves exactly like std::string.
string_view x = "abccba";
auto x = "abccba"_sv;
std::string y = "abccba";
CAF_CHECK_EQUAL(x.rfind('a'), y.rfind('a'));
CAF_CHECK_EQUAL(x.rfind('b'), y.rfind('b'));
......@@ -143,7 +143,7 @@ CAF_TEST(rfind) {
CAF_TEST(find_first_of) {
// Check whether string_view behaves exactly like std::string.
string_view x = "abcdef";
auto x = "abcdef"_sv;
std::string y = "abcdef";
CAF_CHECK_EQUAL(x.find_first_of('a'), y.find_first_of('a'));
CAF_CHECK_EQUAL(x.find_first_of('b'), y.find_first_of('b'));
......@@ -160,7 +160,7 @@ CAF_TEST(find_first_of) {
CAF_TEST(find_last_of) {
// Check whether string_view behaves exactly like std::string.
string_view x = "abcdef";
auto x = "abcdef"_sv;
std::string y = "abcdef";
CAF_CHECK_EQUAL(x.find_last_of('a'), y.find_last_of('a'));
CAF_CHECK_EQUAL(x.find_last_of('b'), y.find_last_of('b'));
......@@ -177,7 +177,7 @@ CAF_TEST(find_last_of) {
CAF_TEST(find_first_not_of) {
// Check whether string_view behaves exactly like std::string.
string_view x = "abcdef";
auto x = "abcdef"_sv;
std::string y = "abcdef";
CAF_CHECK_EQUAL(x.find_first_not_of('a'), y.find_first_not_of('a'));
CAF_CHECK_EQUAL(x.find_first_not_of('b'), y.find_first_not_of('b'));
......@@ -197,7 +197,7 @@ CAF_TEST(find_first_not_of) {
CAF_TEST(find_last_not_of) {
// Check whether string_view behaves exactly like std::string.
string_view x = "abcdef";
auto x = "abcdef"_sv;
std::string y = "abcdef";
CAF_CHECK_EQUAL(x.find_last_not_of('a'), y.find_last_not_of('a'));
CAF_CHECK_EQUAL(x.find_last_not_of('b'), y.find_last_not_of('b'));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment