summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdwin Mons <edwin.mons@isode.com>2018-10-24 13:37:33 (GMT)
committerEdwin Mons <edwin.mons@isode.com>2018-10-24 16:15:21 (GMT)
commit1c71c5a77e037038c581a68774c96fad9a79030b (patch)
tree3ee82bd0d84aa1d4c33d69948ca10952bda9cd35 /Swiften/IDN/UnitTest/IDNConverterTest.cpp
parent0f4a77303fedfaa57977d6ca528799305eac9367 (diff)
downloadswift-1c71c5a77e037038c581a68774c96fad9a79030b.zip
swift-1c71c5a77e037038c581a68774c96fad9a79030b.tar.bz2
Fix buffer overrun in LibIDNConverter
When Swift::LibIDNConverter::getStringPrepared was called with an input of 1024 or more characters, stringprep would be called on a memory region that wasn't NUL-terminated. It also blindly trimmed the input to 1024 bytes, even though there may be input longer than that that still results in a valid 1023 byte prepped string. IDNConverterTest has been converted to gtest, as cppunit cannot deal with testing for std::exceptions being thrown on at least macOS Test-Information: Unit tests pass on macOS 10.13 and Debian 9 Before fix, the newly added unit tests triggered an ASan abort due to a buffer overrun. After fix, all unit tests pass, even with ASan enabled. Change-Id: Ia3e51a39f5db1de32b8f8bb388f81ca041136df7
Diffstat (limited to 'Swiften/IDN/UnitTest/IDNConverterTest.cpp')
-rw-r--r--Swiften/IDN/UnitTest/IDNConverterTest.cpp114
1 files changed, 65 insertions, 49 deletions
diff --git a/Swiften/IDN/UnitTest/IDNConverterTest.cpp b/Swiften/IDN/UnitTest/IDNConverterTest.cpp
index 508a28c..c5f94d0 100644
--- a/Swiften/IDN/UnitTest/IDNConverterTest.cpp
+++ b/Swiften/IDN/UnitTest/IDNConverterTest.cpp
@@ -1,64 +1,80 @@
1/* 1/*
2 * Copyright (c) 2010-2016 Isode Limited. 2 * Copyright (c) 2010-2018 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
6 6
7#include <memory> 7#include <memory>
8 8
9#include <cppunit/extensions/HelperMacros.h> 9#include <gtest/gtest.h>
10#include <cppunit/extensions/TestFactoryRegistry.h>
11 10
12#include <Swiften/IDN/IDNConverter.h> 11#include <Swiften/IDN/IDNConverter.h>
13#include <Swiften/IDN/PlatformIDNConverter.h> 12#include <Swiften/IDN/PlatformIDNConverter.h>
14 13
15using namespace Swift; 14using namespace Swift;
16 15
17class IDNConverterTest : public CppUnit::TestFixture { 16class IDNConverterTest : public ::testing::Test {
18 CPPUNIT_TEST_SUITE(IDNConverterTest); 17
19 CPPUNIT_TEST(testStringPrep); 18protected:
20 CPPUNIT_TEST(testStringPrep_Empty); 19 virtual void SetUp() {
21 CPPUNIT_TEST(testGetEncoded); 20 testling_ = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create());
22 CPPUNIT_TEST(testGetEncoded_International); 21 }
23 CPPUNIT_TEST(testGetEncoded_Invalid); 22
24 CPPUNIT_TEST_SUITE_END(); 23 std::shared_ptr<IDNConverter> testling_;
25
26 public:
27 void setUp() {
28 testling = std::shared_ptr<IDNConverter>(PlatformIDNConverter::create());
29 }
30
31 void testStringPrep() {
32 std::string result = testling->getStringPrepared("tron\xc3\x87on", IDNConverter::NamePrep);
33
34 CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), result);
35 }
36
37 void testStringPrep_Empty() {
38 CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::NamePrep));
39 CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::XMPPNodePrep));
40 CPPUNIT_ASSERT_EQUAL(std::string(""), testling->getStringPrepared("", IDNConverter::XMPPResourcePrep));
41 }
42
43 void testGetEncoded() {
44 boost::optional<std::string> result = testling->getIDNAEncoded("www.swift.im");
45 CPPUNIT_ASSERT(!!result);
46 CPPUNIT_ASSERT_EQUAL(std::string("www.swift.im"), *result);
47 }
48
49 void testGetEncoded_International() {
50 boost::optional<std::string> result = testling->getIDNAEncoded("www.tron\xc3\x87on.com");
51 CPPUNIT_ASSERT(!!result);
52 CPPUNIT_ASSERT_EQUAL(std::string("www.xn--tronon-zua.com"), *result);
53 }
54
55 void testGetEncoded_Invalid() {
56 boost::optional<std::string> result = testling->getIDNAEncoded("www.foo,bar.com");
57 CPPUNIT_ASSERT(!result);
58 }
59
60 private:
61 std::shared_ptr<IDNConverter> testling;
62}; 24};
63 25
64CPPUNIT_TEST_SUITE_REGISTRATION(IDNConverterTest); 26TEST_F(IDNConverterTest, testStringPrep) {
27 std::string result = testling_->getStringPrepared("tron\xc3\x87on", IDNConverter::NamePrep);
28
29 ASSERT_EQ(std::string("tron\xc3\xa7on"), result);
30}
31
32TEST_F(IDNConverterTest, testStringPrep_Empty) {
33 ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::NamePrep));
34 ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::XMPPNodePrep));
35 ASSERT_EQ(std::string(""), testling_->getStringPrepared("", IDNConverter::XMPPResourcePrep));
36}
37
38TEST_F(IDNConverterTest, testStringPrep_MaximumOutputSize) {
39 const std::string input(1023, 'x');
40 ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::NamePrep));
41 ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep));
42 ASSERT_EQ(input, testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep));
43}
44
45TEST_F(IDNConverterTest, testStringPrep_TooLong) {
46 const std::string input(1024, 'x');
47 ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::NamePrep), std::exception);
48 ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep), std::exception);
49 ASSERT_THROW(testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep), std::exception);
50}
51
52TEST_F(IDNConverterTest, testStringPrep_ShrinkingBelow1023) {
53 std::string input;
54 std::string expected;
55 // The four byte \u03b1\u0313 UTF-8 string will shrink to the three byte \u1f00
56 for (auto i = 0; i < 300; ++i) {
57 input +="\xce\xb1\xcc\x93"; // UTF-8 repesentation of U+03B1 U+0313
58 expected += "\xe1\xbc\x80"; // UTF-8 representation of U+1F00
59 }
60 ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::NamePrep));
61 ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::XMPPNodePrep));
62 ASSERT_EQ(expected, testling_->getStringPrepared(input, IDNConverter::XMPPResourcePrep));
63}
64
65TEST_F(IDNConverterTest, testGetEncoded) {
66 boost::optional<std::string> result = testling_->getIDNAEncoded("www.swift.im");
67 ASSERT_TRUE(!!result);
68 ASSERT_EQ(std::string("www.swift.im"), *result);
69}
70
71TEST_F(IDNConverterTest, testGetEncoded_International) {
72 boost::optional<std::string> result = testling_->getIDNAEncoded("www.tron\xc3\x87on.com");
73 ASSERT_TRUE(result);
74 ASSERT_EQ(std::string("www.xn--tronon-zua.com"), *result);
75}
76
77TEST_F(IDNConverterTest, testGetEncoded_Invalid) {
78 boost::optional<std::string> result = testling_->getIDNAEncoded("www.foo,bar.com");
79 ASSERT_FALSE(result);
80}