From 2e69a81ccfbba7332ab0455468fa808cf76d9f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rombauts?= Date: Sun, 3 Mar 2019 00:37:44 +0100 Subject: [PATCH] Fix #189 unit test "Column.basis" failing on Visual Studio 2013 The implicit cast to std::string() would fallback to const char* with MSVC 2010-2013 (witch does not work with the NULL char in the middle) Without it, trying to access a binary blob with implicit cast to string ends up converting it to a C-style char*, damaging the data by truncating it to the first null character! --- appveyor.yml | 4 ---- include/SQLiteCpp/Column.h | 6 +++++- tests/Column_test.cpp | 8 +++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d834ae4..3c0cc1d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,10 +23,6 @@ environment: - arch: Win32 - arch: Win64 -matrix: - allow_failures: - - image: Visual Studio 2013 - init: - echo %APPVEYOR_BUILD_WORKER_IMAGE% - %configuration% - %arch% - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (set vs=Visual Studio 15 2017) diff --git a/include/SQLiteCpp/Column.h b/include/SQLiteCpp/Column.h index 1143e69..31158ee 100644 --- a/include/SQLiteCpp/Column.h +++ b/include/SQLiteCpp/Column.h @@ -224,12 +224,16 @@ public: return getBlob(); } -#if !(defined(_MSC_VER) && _MSC_VER < 1900) +#if !defined(_MSC_VER) || _MSC_VER >= 1900 // NOTE : the following is required by GCC and Clang to cast a Column result in a std::string // (error: conversion from ‘SQLite::Column’ to non-scalar type ‘std::string {aka std::basic_string}’) + // and also required for Microsoft Visual Studio 2015 and newer // but is not working under Microsoft Visual Studio 2010, 2012 and 2013 // (error C2440: 'initializing' : cannot convert from 'SQLite::Column' to 'std::basic_string<_Elem,_Traits,_Ax>' // [...] constructor overload resolution was ambiguous) + // WARNING: without it, trying to access a binary blob with implicit cast to string + // ends up converting it to a C-style char*, damaging the data by truncating it to the first null character! + // (see https://github.com/SRombauts/SQLiteCpp/issues/189 Visual Studio 2013: unit test "Column.basis" failing) /** * @brief Inline cast operator to std::string * diff --git a/tests/Column_test.cpp b/tests/Column_test.cpp index f1815a8..9f3eac2 100644 --- a/tests/Column_test.cpp +++ b/tests/Column_test.cpp @@ -68,7 +68,11 @@ TEST(Column, basis) { const int integer = query.getColumn(2); // operator int() const double real = query.getColumn(3); // operator double() const void* pblob = query.getColumn(4); // operator void*() - const std::string sblob = query.getColumn(4); // operator std::string() (or const char* with MSVC) +#if !defined(_MSC_VER) || _MSC_VER >= 1900 + // This implicit cast should use operator std::string() + // but would fallback to const char* with MSVC 2010-2013 (witch does not work with the NULL char in the middle) + const std::string sblob = query.getColumn(4); // operator std::string() +#endif const void* pempty = query.getColumn(5); // operator void*() EXPECT_EQ(1, id1); EXPECT_EQ(1, id2); @@ -81,8 +85,10 @@ TEST(Column, basis) { EXPECT_EQ(-123, integer); EXPECT_EQ(0.123, real); EXPECT_EQ(0, memcmp("bl\0b", pblob, size)); +#if !defined(_MSC_VER) || _MSC_VER >= 1900 EXPECT_EQ((size_t)size, sblob.size()); EXPECT_EQ(0, memcmp("bl\0b", &sblob[0], size)); +#endif EXPECT_EQ(NULL, pempty); }