std::string_views are created pointing to vector-owned strings, but
those strings can use Short String Optimisation (storing the data
inline, i.e. in vector memory). When the vector is resized, the strings
are moved and those string_views now point to invalid memory.

To fix it, use std::deque which does not invalidate pointers on
push_back.

Fixes 5d2be02f68.

Reviewed By: vladislavbelov
Fixes #5950

Differential Revision: https://code.wildfiregames.com/D3441
This was SVN commit r24742.
This commit is contained in:
wraitii 2021-01-21 08:42:05 +00:00
parent 5d2be02f68
commit 1877871be0

View File

@ -24,6 +24,7 @@
#include "ps/Profile.h"
#include <cctype>
#include <deque>
#include <string>
#include <string_view>
#include <vector>
@ -109,7 +110,7 @@ MatchIncludeResult MatchIncludeUntilEOLorEOS(const std::string_view& source, con
bool ResolveIncludesImpl(
std::string_view currentPart,
std::unordered_map<CStr, CStr>& includeCache, const CPreprocessorWrapper::IncludeRetrieverCallback& includeCallback,
std::vector<std::string>& chunks, std::vector<std::string_view>& processedParts)
std::deque<std::string>& chunks, std::vector<std::string_view>& processedParts)
{
static const CStr lineDirective = "#line ";
for (size_t lineStart = 0, line = 1; lineStart < currentPart.size(); ++line)
@ -229,7 +230,9 @@ CStr CPreprocessorWrapper::ResolveIncludes(const CStr& source)
// Stores intermediate blocks of text to avoid additional copying. Should
// be constructed before views and destroyed after (currently guaranteed
// by stack).
std::vector<std::string> chunks;
// Short String Optimisation can make views point to container-managed data,
// so push_back must not invalidate pointers (std::deque guarantees that).
std::deque<std::string> chunks;
// After resolving the following vector should contain a complete list
// to concatenate.
std::vector<std::string_view> processedParts;