diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp
index 350e8498..7a9c6746 100644
--- a/taglib/toolkit/tbytevector.cpp
+++ b/taglib/toolkit/tbytevector.cpp
@@ -158,7 +158,7 @@ ByteVector fromNumber(T value, bool mostSignificantByteFirst)
 template <typename TFloat, typename TInt, Utils::ByteOrder ENDIAN>
 TFloat toFloat(const ByteVector &v, size_t offset)
 {
-  if(offset > v.size() - sizeof(TInt)) {
+  if(offset + sizeof(TInt) > v.size()) {
     debug("toFloat() - offset is out of range. Returning 0.");
     return 0.0;
   }
@@ -195,7 +195,7 @@ long double toFloat80(const ByteVector &v, size_t offset)
 {
   using std::swap;
 
-  if(offset > v.size() - 10) {
+  if(offset + 10 > v.size()) {
     debug("toFloat80() - offset is out of range. Returning 0.");
     return 0.0;
   }
@@ -360,7 +360,7 @@ ByteVector::ByteVector(const char *data, unsigned int length) :
 }
 
 ByteVector::ByteVector(const char *data) :
-  d(std::make_unique<ByteVectorPrivate>(data, static_cast<unsigned int>(::strlen(data))))
+  d(std::make_unique<ByteVectorPrivate>(data, data ? static_cast<unsigned int>(::strlen(data)) : 0))
 {
 }
 
@@ -767,6 +767,9 @@ bool ByteVector::operator!=(const ByteVector &v) const
 
 bool ByteVector::operator==(const char *s) const
 {
+  if(!s)
+    return isEmpty();
+
   if(size() != ::strlen(s))
     return false;
 
diff --git a/taglib/toolkit/tstring.cpp b/taglib/toolkit/tstring.cpp
index f19a6755..046de208 100644
--- a/taglib/toolkit/tstring.cpp
+++ b/taglib/toolkit/tstring.cpp
@@ -195,23 +195,27 @@ String::String(const wchar_t *s) :
 String::String(const wchar_t *s, Type t) :
   d(std::make_shared<StringPrivate>())
 {
-  if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
-    copyFromUTF16(d->data, s, ::wcslen(s), t);
-  }
-  else {
-    debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8.");
+  if(s) {
+    if(t == UTF16 || t == UTF16BE || t == UTF16LE) {
+      copyFromUTF16(d->data, s, ::wcslen(s), t);
+    }
+    else {
+      debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8.");
+    }
   }
 }
 
 String::String(const char *s, Type t) :
   d(std::make_shared<StringPrivate>())
 {
-  if(t == Latin1)
-    copyFromLatin1(d->data, s, ::strlen(s));
-  else if(t == String::UTF8)
-    copyFromUTF8(d->data, s, ::strlen(s));
-  else {
-    debug("String::String() -- const char * should not contain UTF16.");
+  if(s) {
+    if(t == Latin1)
+      copyFromLatin1(d->data, s, ::strlen(s));
+    else if(t == String::UTF8)
+      copyFromUTF8(d->data, s, ::strlen(s));
+    else {
+      debug("String::String() -- const char * should not contain UTF16.");
+    }
   }
 }
 
@@ -546,6 +550,10 @@ bool String::operator!=(const String &s) const
 
 bool String::operator==(const char *s) const
 {
+  if(!s) {
+    return isEmpty();
+  }
+
   const wchar_t *p = toCWString();
 
   while(*p != L'\0' || *s != '\0') {
@@ -562,6 +570,10 @@ bool String::operator!=(const char *s) const
 
 bool String::operator==(const wchar_t *s) const
 {
+  if(!s) {
+    return isEmpty();
+  }
+
   return d->data == s;
 }
 
@@ -580,18 +592,22 @@ String &String::operator+=(const String &s)
 
 String &String::operator+=(const wchar_t *s)
 {
-  detach();
+  if(s) {
+    detach();
 
-  d->data += s;
+    d->data += s;
+  }
   return *this;
 }
 
 String &String::operator+=(const char *s)
 {
-  detach();
+  if(s) {
+    detach();
 
-  for(int i = 0; s[i] != 0; i++)
-    d->data += static_cast<unsigned char>(s[i]);
+    for(int i = 0; s[i] != 0; i++)
+      d->data += static_cast<unsigned char>(s[i]);
+  }
   return *this;
 }
 
diff --git a/tests/test_bytevector.cpp b/tests/test_bytevector.cpp
index 41c172c9..066f01e9 100644
--- a/tests/test_bytevector.cpp
+++ b/tests/test_bytevector.cpp
@@ -23,6 +23,7 @@
  *   http://www.mozilla.org/MPL/                                           *
  ***************************************************************************/
 
+#include <cstring>
 #define _USE_MATH_DEFINES
 #include <cmath>
 
@@ -53,6 +54,7 @@ class TestByteVector : public CppUnit::TestFixture
   CPPUNIT_TEST(testAppend1);
   CPPUNIT_TEST(testAppend2);
   CPPUNIT_TEST(testBase64);
+  CPPUNIT_TEST(testEmpty);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -612,6 +614,94 @@ public:
 
   }
 
+  void testEmpty()
+  {
+    const ByteVector empty;
+    const ByteVector notEmpty("A");
+    ByteVector mutEmpty;
+
+    CPPUNIT_ASSERT_EQUAL(empty, ByteVector(""));
+    CPPUNIT_ASSERT_EQUAL(empty, ByteVector("", 0));
+    CPPUNIT_ASSERT_EQUAL(empty, ByteVector(0U));
+    CPPUNIT_ASSERT_EQUAL(empty, ByteVector(empty, 0, 0));
+    CPPUNIT_ASSERT_EQUAL(empty, ByteVector(notEmpty, 1, 0));
+    CPPUNIT_ASSERT_EQUAL(empty, ByteVector(static_cast<const char *>(nullptr)));
+    CPPUNIT_ASSERT_EQUAL(empty, ByteVector(static_cast<const char *>(nullptr), 0));
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.setData("", 0), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.setData(""), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.setData(nullptr, 0), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.setData(nullptr), empty);
+    CPPUNIT_ASSERT(!empty.data());
+    CPPUNIT_ASSERT(!mutEmpty.data());
+    CPPUNIT_ASSERT_EQUAL(empty.mid(0), empty);
+    CPPUNIT_ASSERT_EQUAL(empty.at(0), '\0');
+    // Note that the behavior of ByteVector::find() with an empty pattern is
+    // not consistent with String::find() and std::string::find().
+    CPPUNIT_ASSERT_EQUAL(empty.find(mutEmpty), -1);
+    CPPUNIT_ASSERT_EQUAL(empty.find(notEmpty), -1);
+    CPPUNIT_ASSERT_EQUAL(notEmpty.find(empty), -1);
+    CPPUNIT_ASSERT_EQUAL(empty.find('\0'), -1);
+    CPPUNIT_ASSERT_EQUAL(empty.rfind(mutEmpty), -1);
+    CPPUNIT_ASSERT_EQUAL(empty.rfind(notEmpty), -1);
+    CPPUNIT_ASSERT_EQUAL(notEmpty.rfind(empty), -1);
+    CPPUNIT_ASSERT_EQUAL(empty.containsAt(mutEmpty, 0), false);
+    CPPUNIT_ASSERT_EQUAL(empty.startsWith(mutEmpty), false);
+    CPPUNIT_ASSERT_EQUAL(empty.startsWith(notEmpty), false);
+    CPPUNIT_ASSERT_EQUAL(notEmpty.startsWith(empty), false);
+    CPPUNIT_ASSERT_EQUAL(empty.endsWith(mutEmpty), false);
+    CPPUNIT_ASSERT_EQUAL(empty.endsWithPartialMatch(mutEmpty), -1);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.replace('a', 'b'), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.replace("abc", ""), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.append(empty), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.append(notEmpty), notEmpty);
+    mutEmpty.clear();
+    CPPUNIT_ASSERT_EQUAL(mutEmpty, empty);
+    CPPUNIT_ASSERT_EQUAL(ByteVector(notEmpty).append(empty), notEmpty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.append('A'), notEmpty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.resize(0), empty);
+    CPPUNIT_ASSERT_EQUAL(empty.size(), 0U);
+    CPPUNIT_ASSERT(empty.begin() == empty.end());
+    CPPUNIT_ASSERT(empty.cbegin() == empty.cend());
+    CPPUNIT_ASSERT(empty.rbegin() == empty.rend());
+    CPPUNIT_ASSERT(mutEmpty.begin() == mutEmpty.end());
+    CPPUNIT_ASSERT(mutEmpty.rbegin() == mutEmpty.rend());
+    CPPUNIT_ASSERT(empty.isEmpty());
+    CPPUNIT_ASSERT_EQUAL(empty.toUInt(), 0U);
+    CPPUNIT_ASSERT_EQUAL(empty.toUInt(0, true), 0U);
+    CPPUNIT_ASSERT_EQUAL(empty.toUInt(0, 0, true), 0U);
+    CPPUNIT_ASSERT_EQUAL(empty.toShort(), static_cast<short>(0));
+    CPPUNIT_ASSERT_EQUAL(empty.toShort(0, true), static_cast<short>(0));
+    CPPUNIT_ASSERT_EQUAL(empty.toUShort(), static_cast<unsigned short>(0));
+    CPPUNIT_ASSERT_EQUAL(empty.toUShort(0, true), static_cast<unsigned short>(0));
+    CPPUNIT_ASSERT_EQUAL(empty.toLongLong(), 0LL);
+    CPPUNIT_ASSERT_EQUAL(empty.toLongLong(0, true), 0LL);
+    CPPUNIT_ASSERT_EQUAL(empty.toULongLong(), 0ULL);
+    CPPUNIT_ASSERT_EQUAL(empty.toULongLong(0, true), 0ULL);
+    CPPUNIT_ASSERT_EQUAL(empty.toFloat32LE(0), 0.f);
+    CPPUNIT_ASSERT_EQUAL(empty.toFloat32BE(0), 0.f);
+    CPPUNIT_ASSERT_EQUAL(empty.toFloat64LE(0), 0.);
+    CPPUNIT_ASSERT_EQUAL(empty.toFloat64BE(0), 0.);
+    CPPUNIT_ASSERT_EQUAL(empty.toFloat80LE(0), 0.l);
+    CPPUNIT_ASSERT_EQUAL(empty.toFloat80BE(0), 0.l);
+    CPPUNIT_ASSERT(empty == mutEmpty);
+    CPPUNIT_ASSERT(empty != notEmpty);
+    CPPUNIT_ASSERT(empty == "");
+    CPPUNIT_ASSERT(empty != " ");
+    CPPUNIT_ASSERT(empty == static_cast<const char *>(nullptr));
+    CPPUNIT_ASSERT(!(empty != static_cast<const char *>(nullptr)));
+    CPPUNIT_ASSERT(empty < notEmpty);
+    CPPUNIT_ASSERT(!(empty > notEmpty));
+    CPPUNIT_ASSERT_EQUAL(empty + mutEmpty, empty);
+    CPPUNIT_ASSERT_EQUAL(empty + notEmpty, notEmpty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty = static_cast<const char *>(nullptr), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty = notEmpty, notEmpty);
+    ByteVector tmp;
+    mutEmpty.swap(tmp);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty, empty);
+    CPPUNIT_ASSERT_EQUAL(empty.toHex(), empty);
+    CPPUNIT_ASSERT_EQUAL(empty.toBase64(), empty);
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestByteVector);
diff --git a/tests/test_string.cpp b/tests/test_string.cpp
index 07caa62c..fa188380 100644
--- a/tests/test_string.cpp
+++ b/tests/test_string.cpp
@@ -23,9 +23,12 @@
  *   http://www.mozilla.org/MPL/                                           *
  ***************************************************************************/
 
+#include <string>
 #include <cstring>
 
 #include "tstring.h"
+#include "tstringlist.h"
+#include "tbytevector.h"
 #include "tutils.h"
 #include <cppunit/extensions/HelperMacros.h>
 
@@ -54,6 +57,7 @@ class TestString : public CppUnit::TestFixture
   CPPUNIT_TEST(testEncodeNonBMP);
   CPPUNIT_TEST(testIterator);
   CPPUNIT_TEST(testInvalidUTF8);
+  CPPUNIT_TEST(testEmpty);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -370,6 +374,80 @@ public:
     CPPUNIT_ASSERT(String(ByteVector("\xED\xB0\x80\xED\xA0\x80"), String::UTF8).isEmpty());
   }
 
+  void testEmpty()
+  {
+    const String empty;
+    const String notEmpty("A");
+    String mutEmpty;
+
+    CPPUNIT_ASSERT_EQUAL(empty, String(""));
+    CPPUNIT_ASSERT_EQUAL(empty, String(std::wstring()));
+    CPPUNIT_ASSERT_EQUAL(empty, String(static_cast<const wchar_t *>(nullptr)));
+    CPPUNIT_ASSERT(empty != String('\0'));
+    CPPUNIT_ASSERT_EQUAL(empty, String(L'\0'));
+    CPPUNIT_ASSERT_EQUAL(empty, String(static_cast<const char *>(nullptr)));
+    CPPUNIT_ASSERT_EQUAL(empty, String(ByteVector()));
+    CPPUNIT_ASSERT_EQUAL(empty.to8Bit(), std::string());
+    CPPUNIT_ASSERT_EQUAL(empty.toWString(), std::wstring());
+    CPPUNIT_ASSERT_EQUAL(::strlen(empty.toCString()), (size_t)0);
+    CPPUNIT_ASSERT_EQUAL(::wcslen(empty.toCWString()), (size_t)0);
+    CPPUNIT_ASSERT(empty.begin() == empty.end());
+    CPPUNIT_ASSERT(empty.cbegin() == empty.cend());
+    CPPUNIT_ASSERT(mutEmpty.begin() == mutEmpty.end());
+    CPPUNIT_ASSERT_EQUAL(empty.find(mutEmpty), 0);
+    CPPUNIT_ASSERT_EQUAL(empty.find(notEmpty), -1);
+    CPPUNIT_ASSERT_EQUAL(notEmpty.find(empty), 0);
+    CPPUNIT_ASSERT_EQUAL(empty.rfind(mutEmpty), 0);
+    CPPUNIT_ASSERT_EQUAL(empty.rfind(notEmpty), -1);
+    CPPUNIT_ASSERT_EQUAL(notEmpty.rfind(empty), 1);
+    CPPUNIT_ASSERT_EQUAL(empty.split(), StringList(empty));
+    CPPUNIT_ASSERT_EQUAL(empty.startsWith(mutEmpty), true);
+    CPPUNIT_ASSERT_EQUAL(empty.startsWith(notEmpty), false);
+    CPPUNIT_ASSERT_EQUAL(notEmpty.startsWith(empty), true);
+    CPPUNIT_ASSERT_EQUAL(empty.substr(0), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.append(empty), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty.append(notEmpty), notEmpty);
+    mutEmpty.clear();
+    CPPUNIT_ASSERT_EQUAL(mutEmpty, empty);
+    CPPUNIT_ASSERT_EQUAL(String(notEmpty).append(empty), notEmpty);
+    CPPUNIT_ASSERT_EQUAL(empty.upper(), empty);
+    CPPUNIT_ASSERT_EQUAL(empty.size(), 0U);
+    CPPUNIT_ASSERT_EQUAL(empty.length(), 0U);
+    CPPUNIT_ASSERT_EQUAL(empty.isEmpty(), true);
+    CPPUNIT_ASSERT_EQUAL(empty.data(String::Latin1), ByteVector());
+    CPPUNIT_ASSERT_EQUAL(empty.data(String::UTF16LE), ByteVector());
+    bool ok;
+    empty.toInt(&ok);
+    CPPUNIT_ASSERT(!ok);
+    CPPUNIT_ASSERT_EQUAL(empty.stripWhiteSpace(), empty);
+    CPPUNIT_ASSERT_EQUAL(empty.isLatin1(), true);
+    CPPUNIT_ASSERT_EQUAL(empty.isAscii(), true);
+    CPPUNIT_ASSERT(empty == mutEmpty);
+    CPPUNIT_ASSERT(empty != notEmpty);
+    CPPUNIT_ASSERT(empty == "");
+    CPPUNIT_ASSERT(empty != " ");
+    CPPUNIT_ASSERT(empty == L"");
+    CPPUNIT_ASSERT(empty != L" ");
+    CPPUNIT_ASSERT(empty == static_cast<const char *>(nullptr));
+    CPPUNIT_ASSERT(!(empty != static_cast<const char *>(nullptr)));
+    CPPUNIT_ASSERT(empty == static_cast<const wchar_t *>(nullptr));
+    CPPUNIT_ASSERT(!(empty != static_cast<const wchar_t *>(nullptr)));
+    CPPUNIT_ASSERT_EQUAL(mutEmpty += empty, empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty += notEmpty, notEmpty);
+    mutEmpty.clear();
+    CPPUNIT_ASSERT_EQUAL(mutEmpty += static_cast<const char *>(nullptr), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty += static_cast<const wchar_t *>(nullptr), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty = static_cast<const char *>(nullptr), empty);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty = static_cast<const wchar_t *>(nullptr), empty);
+    String tmp;
+    mutEmpty.swap(tmp);
+    CPPUNIT_ASSERT_EQUAL(mutEmpty, empty);
+    CPPUNIT_ASSERT_EQUAL(empty < notEmpty, true);
+    CPPUNIT_ASSERT_EQUAL(empty + mutEmpty, empty);
+    CPPUNIT_ASSERT_EQUAL(empty + notEmpty, notEmpty);
+    CPPUNIT_ASSERT_EQUAL(empty + static_cast<const char *>(nullptr), empty);
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestString);