Commit f5aacb89 authored by Erik Verbruggen's avatar Erik Verbruggen
Browse files

[C++] Robustness fix for boost's preprocessor/seq/fold_right.hpp.



Change-Id: I11f6cff556519b768dd5d979dfd184809ed18291
Reviewed-by: default avatarRoberto Raggi <roberto.raggi@nokia.com>
parent 3781a177
...@@ -73,7 +73,8 @@ ...@@ -73,7 +73,8 @@
namespace { namespace {
enum { enum {
eagerExpansion = 1, eagerExpansion = 1,
MAX_TOKEN_EXPANSION_COUNT = 5000 MAX_TOKEN_EXPANSION_COUNT = 5000,
MAX_TOKEN_BUFFER_DEPTH = 16000, // for when macros are using some kind of right-folding, this is the list of "delayed" buffers waiting to be expanded after the current one.
}; };
} }
...@@ -109,22 +110,20 @@ struct TokenBuffer ...@@ -109,22 +110,20 @@ struct TokenBuffer
std::list<PPToken> tokens; std::list<PPToken> tokens;
const Macro *macro; const Macro *macro;
TokenBuffer *next; TokenBuffer *next;
QVector<QByteArray> blockedMacros;
template <typename _Iterator> TokenBuffer(const PPToken *start, const PPToken *end, const Macro *macro, TokenBuffer *next)
TokenBuffer(_Iterator firstToken, _Iterator lastToken, const Macro *macro, TokenBuffer *next) : tokens(start, end), macro(macro), next(next)
: tokens(firstToken, lastToken), macro(macro), next(next)
{} {}
bool isBlocked(const QByteArray &macroName) const { bool isBlocked(const Macro *macro) const {
if (!macro)
return false;
for (const TokenBuffer *it = this; it; it = it->next) for (const TokenBuffer *it = this; it; it = it->next)
if (it->blockedMacros.contains(macroName)) if (it->macro == macro && it->macro->name() == macro->name())
return true; return true;
return false; return false;
} }
void blockMacro(const QByteArray &macroName)
{ blockedMacros.append(macroName); }
}; };
struct Value struct Value
...@@ -527,6 +526,7 @@ Preprocessor::State::State() ...@@ -527,6 +526,7 @@ Preprocessor::State::State()
, m_trueTest(MAX_LEVEL) , m_trueTest(MAX_LEVEL)
, m_ifLevel(0) , m_ifLevel(0)
, m_tokenBuffer(0) , m_tokenBuffer(0)
, m_tokenBufferDepth(0)
, m_inPreprocessorDirective(false) , m_inPreprocessorDirective(false)
, m_result(0) , m_result(0)
, m_markGeneratedTokens(true) , m_markGeneratedTokens(true)
...@@ -538,6 +538,37 @@ Preprocessor::State::State() ...@@ -538,6 +538,37 @@ Preprocessor::State::State()
m_trueTest[m_ifLevel] = false; m_trueTest[m_ifLevel] = false;
} }
void Preprocessor::State::pushTokenBuffer(const PPToken *start, const PPToken *end, const Macro *macro)
{
if (m_tokenBufferDepth <= MAX_TOKEN_BUFFER_DEPTH) {
#ifdef COMPRESS_TOKEN_BUFFER
// This does not work correctly for boost's preprocessor library, or that library exposes a bug in the code.
if (macro || !m_tokenBuffer) {
m_tokenBuffer = new TokenBuffer(start, end, macro, m_tokenBuffer);
++m_tokenBufferDepth;
} else {
m_tokenBuffer->tokens.insert(m_tokenBuffer->tokens.begin(), start, end);
}
// qDebug()<<"New depth:" << m_tokenBufferDepth << "with buffer size:" << m_tokenBuffer->tokens.size();
#else
m_tokenBuffer = new TokenBuffer(start, end, macro, m_tokenBuffer);
++m_tokenBufferDepth;
#endif
} else {
//### Should we tell the user that his source is insane?
// qDebug() << "Macro insanity level reached in" << m_currentFileName;
}
}
void Preprocessor::State::popTokenBuffer()
{
TokenBuffer *r = m_tokenBuffer;
m_tokenBuffer = m_tokenBuffer->next;
delete r;
if (m_tokenBufferDepth)
--m_tokenBufferDepth;
}
Preprocessor::Preprocessor(Client *client, Environment *env) Preprocessor::Preprocessor(Client *client, Environment *env)
: m_client(client) : m_client(client)
...@@ -665,10 +696,7 @@ void Preprocessor::handleDefined(PPToken *tk) ...@@ -665,10 +696,7 @@ void Preprocessor::handleDefined(PPToken *tk)
void Preprocessor::pushToken(Preprocessor::PPToken *tk) void Preprocessor::pushToken(Preprocessor::PPToken *tk)
{ {
const PPToken currentTokenBuffer[] = { *tk }; const PPToken currentTokenBuffer[] = { *tk };
m_state.m_tokenBuffer = new TokenBuffer(currentTokenBuffer, m_state.pushTokenBuffer(currentTokenBuffer, currentTokenBuffer + 1, 0);
currentTokenBuffer + 1,
/*macro */ 0,
m_state.m_tokenBuffer);
} }
void Preprocessor::lex(PPToken *tk) void Preprocessor::lex(PPToken *tk)
...@@ -676,9 +704,7 @@ void Preprocessor::lex(PPToken *tk) ...@@ -676,9 +704,7 @@ void Preprocessor::lex(PPToken *tk)
_Lagain: _Lagain:
if (m_state.m_tokenBuffer) { if (m_state.m_tokenBuffer) {
if (m_state.m_tokenBuffer->tokens.empty()) { if (m_state.m_tokenBuffer->tokens.empty()) {
TokenBuffer *r = m_state.m_tokenBuffer; m_state.popTokenBuffer();
m_state.m_tokenBuffer = m_state.m_tokenBuffer->next;
delete r;
goto _Lagain; goto _Lagain;
} }
*tk = m_state.m_tokenBuffer->tokens.front(); *tk = m_state.m_tokenBuffer->tokens.front();
...@@ -767,12 +793,11 @@ bool Preprocessor::handleIdentifier(PPToken *tk) ...@@ -767,12 +793,11 @@ bool Preprocessor::handleIdentifier(PPToken *tk)
} }
const QByteArray macroName = macroNameRef.toByteArray(); const QByteArray macroName = macroNameRef.toByteArray();
if (tk->generated() && m_state.m_tokenBuffer && m_state.m_tokenBuffer->isBlocked(macroName))
return false;
Macro *macro = m_env->resolve(macroName); Macro *macro = m_env->resolve(macroName);
if (!macro) if (!macro)
return false; return false;
if (tk->generated() && m_state.m_tokenBuffer && m_state.m_tokenBuffer->isBlocked(macro))
return false;
// qDebug() << "expanding" << macro->name() << "on line" << tk->lineno; // qDebug() << "expanding" << macro->name() << "on line" << tk->lineno;
if (m_client) if (m_client)
...@@ -802,9 +827,7 @@ bool Preprocessor::handleIdentifier(PPToken *tk) ...@@ -802,9 +827,7 @@ bool Preprocessor::handleIdentifier(PPToken *tk)
firstNewTk.f.whitespace = true; // the macro call is removed, so space the first token correctly. firstNewTk.f.whitespace = true; // the macro call is removed, so space the first token correctly.
} }
m_state.m_tokenBuffer = new TokenBuffer(body.begin(), body.end(), m_state.pushTokenBuffer(body.begin(), body.end(), macro);
macro, m_state.m_tokenBuffer);
m_state.m_tokenBuffer->blockMacro(macroName);
if (m_client) if (m_client)
m_client->stopExpandingMacro(tk->offset, *macro); m_client->stopExpandingMacro(tk->offset, *macro);
......
...@@ -98,6 +98,9 @@ private: ...@@ -98,6 +98,9 @@ private:
struct State { struct State {
State(); State();
void pushTokenBuffer(const PPToken *start, const PPToken *end, const Macro *macro);
void popTokenBuffer();
QString m_currentFileName; QString m_currentFileName;
QByteArray m_source; QByteArray m_source;
...@@ -106,6 +109,7 @@ private: ...@@ -106,6 +109,7 @@ private:
QBitArray m_trueTest; QBitArray m_trueTest;
int m_ifLevel; int m_ifLevel;
Internal::TokenBuffer *m_tokenBuffer; Internal::TokenBuffer *m_tokenBuffer;
unsigned m_tokenBufferDepth;
bool m_inPreprocessorDirective; bool m_inPreprocessorDirective;
QByteArray *m_result; QByteArray *m_result;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment