mirror of
https://github.com/boostorg/serialization.git
synced 2026-07-22 13:43:39 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 37f1928858 |
@@ -244,15 +244,7 @@ jobs:
|
||||
run: |
|
||||
cd ../boost-root
|
||||
export ADDRMD=${{matrix.address-model}}
|
||||
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release
|
||||
|
||||
- name: Run examples
|
||||
run: |
|
||||
cd ../boost-root
|
||||
export ADDRMD=${{matrix.address-model}}
|
||||
# The demos use fixed temp filenames, so run them serially (-j1)
|
||||
# to avoid concurrent runs clobbering each other's archive files.
|
||||
./b2 -j1 libs/$LIBRARY/example toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release
|
||||
./b2 -j3 libs/$LIBRARY/test libs/$LIBRARY/example toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release
|
||||
|
||||
windows:
|
||||
strategy:
|
||||
@@ -307,15 +299,7 @@ jobs:
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root
|
||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
|
||||
- name: Run examples
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root
|
||||
rem The demos use fixed temp filenames, so run them serially (-j1)
|
||||
rem to avoid concurrent runs clobbering each other's archive files.
|
||||
b2 -j1 libs/%LIBRARY%/example toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
b2 -j3 libs/%LIBRARY%/test libs/%LIBRARY%/example toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
|
||||
|
||||
posix-cmake-subdir:
|
||||
strategy:
|
||||
|
||||
@@ -11,8 +11,6 @@ project libs/serialization/example
|
||||
: requirements <library>../build//boost_serialization
|
||||
;
|
||||
|
||||
import testing ;
|
||||
|
||||
import ../util/test :
|
||||
run-template
|
||||
run-invoke
|
||||
|
||||
@@ -189,14 +189,7 @@ xml_iarchive_impl<Archive>::~xml_iarchive_impl(){
|
||||
if(boost::core::uncaught_exceptions() > 0)
|
||||
return;
|
||||
if(0 == (this->get_flags() & no_header)){
|
||||
// windup() parses the trailing end tag; an exception must not escape
|
||||
// this (implicitly noexcept) destructor and terminate the process.
|
||||
// A stream error while consuming the trailer is not worth that. #99
|
||||
BOOST_TRY {
|
||||
gimpl->windup(is);
|
||||
}
|
||||
BOOST_CATCH(...) {}
|
||||
BOOST_CATCH_END
|
||||
gimpl->windup(is);
|
||||
}
|
||||
}
|
||||
} // namespace archive
|
||||
|
||||
@@ -177,14 +177,7 @@ xml_wiarchive_impl<Archive>::~xml_wiarchive_impl(){
|
||||
if(boost::core::uncaught_exceptions() > 0)
|
||||
return;
|
||||
if(0 == (this->get_flags() & no_header)){
|
||||
// windup() parses the trailing end tag; an exception must not escape
|
||||
// this (implicitly noexcept) destructor and terminate the process.
|
||||
// A stream error while consuming the trailer is not worth that. #99
|
||||
BOOST_TRY {
|
||||
gimpl->windup(is);
|
||||
}
|
||||
BOOST_CATCH(...) {}
|
||||
BOOST_CATCH_END
|
||||
gimpl->windup(is);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,8 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// GCC's <filesystem> before version 9 is the initial, incomplete
|
||||
// implementation (shipped in a separate libstdc++fs and buggy at runtime),
|
||||
// so the feature is disabled there.
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<filesystem>) && (BOOST_CXX_VERSION >= 201703L) \
|
||||
&& ! (defined(__GNUC__) && ! defined(__clang__) && __GNUC__ < 9)
|
||||
# if __has_include(<filesystem>) && (BOOST_CXX_VERSION >= 201703L)
|
||||
# define BOOST_SERIALIZATION_HAS_STD_FILESYSTEM
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -255,7 +255,7 @@ basic_oarchive_impl::save_object(
|
||||
if(bos.class_info()){
|
||||
if( ! co.m_initialized){
|
||||
ar.vsave(class_id_optional_type(co.m_class_id));
|
||||
ar.vsave(tracking_type(co.m_bos_ptr->tracking(m_flags)));
|
||||
ar.vsave(tracking_type(bos.tracking(m_flags)));
|
||||
ar.vsave(version_type(bos.version()));
|
||||
(const_cast<cobject_type &>(co)).m_initialized = true;
|
||||
}
|
||||
@@ -343,7 +343,7 @@ basic_oarchive_impl::save_pointer(
|
||||
}
|
||||
}
|
||||
if(bos.class_info()){
|
||||
ar.vsave(tracking_type(co.m_bos_ptr->tracking(m_flags)));
|
||||
ar.vsave(tracking_type(bos.tracking(m_flags)));
|
||||
ar.vsave(version_type(bos.version()));
|
||||
}
|
||||
(const_cast<cobject_type &>(co)).m_initialized = true;
|
||||
|
||||
@@ -191,15 +191,6 @@ bool basic_xml_grammar<CharType>::my_parse(
|
||||
for(;;){
|
||||
CharType result;
|
||||
is.get(result);
|
||||
// Reaching end of input while scanning for the next character is the
|
||||
// normal way an archive ends (e.g. windup() consuming the trailer);
|
||||
// it is not a stream error. get() sets both eofbit and failbit at end
|
||||
// of stream, so test eof() *before* fail() -- otherwise the normal
|
||||
// termination is misreported as input_stream_error, which is fatal
|
||||
// when it surfaces in the (noexcept) archive destructor via windup().
|
||||
// See #99.
|
||||
if(is.eof())
|
||||
return false;
|
||||
if(is.fail()){
|
||||
boost::serialization::throw_exception(
|
||||
boost::archive::archive_exception(
|
||||
@@ -208,6 +199,8 @@ bool basic_xml_grammar<CharType>::my_parse(
|
||||
)
|
||||
);
|
||||
}
|
||||
if(is.eof())
|
||||
return false;
|
||||
arg += result;
|
||||
if(result == delimiter)
|
||||
break;
|
||||
|
||||
@@ -146,14 +146,11 @@ if ! $(BOOST_ARCHIVE_LIST) {
|
||||
# we suppress tests of our dlls when using static libraries
|
||||
|
||||
[ test-bsl-run test_dll_simple : : dll_a : <link>static:<build>no ]
|
||||
[ test-bsl-run test_dll_base_pointer : : dll_polymorphic_base dll_polymorphic_derived2 : <link>static:<build>no ]
|
||||
# [ test-bsl-run test_dll_plugin : : dll_derived2 : <link>static:<build>no <target-os>linux:<linkflags>-ldl ]
|
||||
|
||||
[ test-bsl-run test_private_ctor ]
|
||||
[ test-bsl-run test_reset_object_address : A ]
|
||||
[ test-bsl-run test_void_cast ]
|
||||
[ test-bsl-run test_xml_trailing_whitespace ]
|
||||
[ test-bsl-run test_xml_missing_nvp ]
|
||||
[ test-bsl-run test_mult_archive_types : : : [ requires std_wstreambuf ] ]
|
||||
[ test-bsl-run test_iterators : : : [ requires std_wstreambuf ] ]
|
||||
[ test-bsl-run test_iterators_base64 ]
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// test_dll_base_pointer.cpp
|
||||
|
||||
// Copyright 2026 Gennaro Prota
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Regression test for issue #117. A derived class defined in a shared
|
||||
// library is serialized and deserialized through a pointer to its abstract
|
||||
// base, from an executable built with hidden symbol visibility.
|
||||
// Historically this failed on GCC/ELF: the per type serializer singletons
|
||||
// were duplicated across the shared library boundary, so the reader could not
|
||||
// map the class id back to the derived type. The round trip must recover an
|
||||
// object of the derived type.
|
||||
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include "test_tools.hpp"
|
||||
|
||||
#ifndef BOOST_NO_CXX11_SMART_PTR
|
||||
|
||||
#include <boost/archive/polymorphic_binary_oarchive.hpp>
|
||||
#include <boost/archive/polymorphic_binary_iarchive.hpp>
|
||||
#include <boost/archive/tmpdir.hpp>
|
||||
|
||||
#include <boost/smart_ptr/make_unique.hpp>
|
||||
#include <boost/serialization/unique_ptr.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
// polymorphic_derived2 (and its base, polymorphic_base) live in the shared
|
||||
// library this test links against
|
||||
#define POLYMORPHIC_DERIVED2_IMPORT
|
||||
#include "polymorphic_derived2.hpp"
|
||||
|
||||
int test_main(int /* argc */, char * /* argv */ []){
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
BOOST_REQUIRE(NULL != testfile);
|
||||
|
||||
std::unique_ptr<polymorphic_base> saved =
|
||||
boost::make_unique<polymorphic_derived2>();
|
||||
{
|
||||
std::ofstream os(testfile, std::ios::binary);
|
||||
boost::archive::polymorphic_binary_oarchive oa(os);
|
||||
boost::archive::polymorphic_oarchive & poa = oa;
|
||||
poa << boost::serialization::make_nvp("ptr", saved);
|
||||
}
|
||||
|
||||
std::unique_ptr<polymorphic_base> loaded;
|
||||
{
|
||||
std::ifstream is(testfile, std::ios::binary);
|
||||
boost::archive::polymorphic_binary_iarchive ia(is);
|
||||
boost::archive::polymorphic_iarchive & pia = ia;
|
||||
pia >> boost::serialization::make_nvp("ptr", loaded);
|
||||
}
|
||||
|
||||
BOOST_CHECK(0 != loaded.get());
|
||||
// the object recovered through the base pointer must be the derived type
|
||||
BOOST_CHECK(0 != dynamic_cast<polymorphic_derived2 *>(loaded.get()));
|
||||
|
||||
std::remove(testfile);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int test_main(int /* argc */, char * /* argv */ []){
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_CXX11_SMART_PTR
|
||||
@@ -17,11 +17,8 @@
|
||||
|
||||
// `std::filesystem::path` is a C++17 feature; when it isn't available, this
|
||||
// test has nothing to exercise and simply succeeds.
|
||||
// Note the guard for GCC < 9, which matches the one in
|
||||
// boost/serialization/filesystem.hpp: see the comment there for the why.
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<filesystem>) && (BOOST_CXX_VERSION >= 201703L) \
|
||||
&& ! (defined(__GNUC__) && ! defined(__clang__) && __GNUC__ < 9)
|
||||
# if __has_include(<filesystem>) && (BOOST_CXX_VERSION >= 201703L)
|
||||
# define BOOST_SERIALIZATION_TEST_STD_FILESYSTEM
|
||||
# endif
|
||||
#endif
|
||||
@@ -32,11 +29,6 @@
|
||||
|
||||
#include <boost/serialization/filesystem.hpp>
|
||||
#include <filesystem>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef BOOST_NO_STD_WSTREAMBUF
|
||||
#include <boost/archive/text_woarchive.hpp>
|
||||
#endif
|
||||
|
||||
void check_roundtrip(const std::filesystem::path & original){
|
||||
const char * testfile = boost::archive::tmpnam(NULL);
|
||||
@@ -65,21 +57,6 @@ std::filesystem::path from_utf8(const std::string & utf8){
|
||||
#endif
|
||||
}
|
||||
|
||||
// The wide *text* archive is the one archive that cannot round-trip non-ASCII
|
||||
// content: it transcodes the narrow UTF-8 std::string through the stream
|
||||
// locale's codecvt (codecvt_null), which mangles bytes outside the ASCII
|
||||
// range. Every other archive in the test list preserves them -- narrow text
|
||||
// and XML store the bytes verbatim, binary stores them raw, and wide XML
|
||||
// installs a UTF-8 codecvt. So the non-ASCII case is exercised everywhere
|
||||
// except that single archive.
|
||||
bool archive_round_trips_non_ascii(){
|
||||
#ifndef BOOST_NO_STD_WSTREAMBUF
|
||||
return ! std::is_same<test_oarchive, boost::archive::text_woarchive>::value;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
int test_main(int /* argc */, char * /* argv */ []){
|
||||
check_roundtrip(std::filesystem::path()); // empty
|
||||
check_roundtrip("foo/bar/baz.txt"); // relative
|
||||
@@ -89,8 +66,7 @@ int test_main(int /* argc */, char * /* argv */ []){
|
||||
// The escapes are the UTF-8 encoding of U+00E9, U+00EF and U+00FC
|
||||
// (e-acute, i-diaeresis, u-diaeresis); written as `\x` so the source
|
||||
// file stays pure ASCII and encoding-independent.
|
||||
if(archive_round_trips_non_ascii())
|
||||
check_roundtrip(from_utf8("caf\xC3\xA9/na\xC3\xAF" "ve/\xC3\xBC.txt"));
|
||||
check_roundtrip(from_utf8("caf\xC3\xA9/na\xC3\xAF" "ve/\xC3\xBC.txt"));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// test_xml_missing_nvp.cpp
|
||||
|
||||
// Copyright 2026 Gennaro Prota
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Regression test for issue #109. Attempting to read an nvp that is not
|
||||
// present throws archive_exception, which the caller may catch. The failed
|
||||
// read consumes the closing tag, so at destruction windup() reaches end of
|
||||
// input -- the same Boost 1.66 my_parse regression as #82/#99, reached by a
|
||||
// different path. The input archive must still destruct without terminating.
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/archive/xml_oarchive.hpp>
|
||||
#include <boost/archive/xml_iarchive.hpp>
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
#include "test_tools.hpp"
|
||||
|
||||
int test_main(int /* argc */, char * /* argv */ []){
|
||||
// Build a valid XML archive holding a single value.
|
||||
std::string content;
|
||||
{
|
||||
std::ostringstream os;
|
||||
{
|
||||
boost::archive::xml_oarchive oa(os);
|
||||
const int x = 42;
|
||||
oa << boost::serialization::make_nvp("x", x);
|
||||
}
|
||||
content = os.str();
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
bool caught = false;
|
||||
{
|
||||
std::istringstream is(content);
|
||||
boost::archive::xml_iarchive ia(is);
|
||||
ia >> boost::serialization::make_nvp("x", x);
|
||||
try {
|
||||
int y = 0;
|
||||
ia >> boost::serialization::make_nvp("not_there", y);
|
||||
} catch (const boost::archive::archive_exception &){
|
||||
caught = true;
|
||||
}
|
||||
// `ia` is destroyed here, after the caught exception. Before the fix,
|
||||
// windup() hit end of input (the failed read consumed the closing
|
||||
// tag) and threw out of the noexcept destructor, terminating.
|
||||
}
|
||||
BOOST_CHECK(42 == x);
|
||||
BOOST_CHECK(caught);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// test_xml_trailing_whitespace.cpp
|
||||
|
||||
// Copyright 2026 Gennaro Prota
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Regression test for issue #99. When an XML input archive is destroyed and
|
||||
// its stream has no closing tag left -- only trailing whitespace before end
|
||||
// of input (a truncated archive; the reported case had the stream "contain
|
||||
// \r\n") -- windup() reaches end of input while scanning for the trailing
|
||||
// tag. End of input there is normal termination, not a stream error, so the
|
||||
// (implicitly noexcept) destructor must complete cleanly rather than throw,
|
||||
// which used to terminate the process.
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/archive/xml_oarchive.hpp>
|
||||
#include <boost/archive/xml_iarchive.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
#include "test_tools.hpp"
|
||||
|
||||
int test_main(int /* argc */, char * /* argv */ []){
|
||||
// Build a valid XML archive holding a single value.
|
||||
std::string content;
|
||||
{
|
||||
std::ostringstream os;
|
||||
{
|
||||
boost::archive::xml_oarchive oa(os);
|
||||
const int x = 42;
|
||||
oa << boost::serialization::make_nvp("x", x);
|
||||
}
|
||||
content = os.str();
|
||||
}
|
||||
|
||||
// Drop the closing document tag and leave only trailing whitespace, so the
|
||||
// input archive's windup() reaches end of input at destruction instead of
|
||||
// finding a tag.
|
||||
const std::string::size_type close = content.rfind("</boost_serialization>");
|
||||
BOOST_REQUIRE(std::string::npos != close);
|
||||
content.erase(close);
|
||||
content += "\r\n";
|
||||
|
||||
int y = 0;
|
||||
{
|
||||
std::istringstream is(content);
|
||||
boost::archive::xml_iarchive ia(is);
|
||||
ia >> boost::serialization::make_nvp("x", y);
|
||||
// `ia` is destroyed here with only trailing whitespace left. Before
|
||||
// the fix, windup() threw input_stream_error out of the noexcept
|
||||
// destructor and terminated the process.
|
||||
}
|
||||
BOOST_CHECK(42 == y);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user