Bug 1159973 - Abort parsing when TokenStream::SourceCoords hits OOM. r=jorendorff

This commit is contained in:
Tooru Fujisawa 2015-05-24 05:38:00 +09:00
parent 487c6066bb
commit eb05619abf
5 changed files with 51 additions and 26 deletions

View File

@ -2289,7 +2289,8 @@ js::LookupAsmJSModuleInCache(ExclusiveContext* cx,
if (!atEnd)
return true;
parser.tokenStream.advance(module->srcEndBeforeCurly());
if (!parser.tokenStream.advance(module->srcEndBeforeCurly()))
return false;
{
// Delay flushing until dynamic linking.

View File

@ -417,7 +417,10 @@ bool
BytecodeEmitter::updateLineNumberNotes(uint32_t offset)
{
TokenStream* ts = &parser->tokenStream;
if (!ts->srcCoords.isOnThisLine(offset, currentLine())) {
bool onThisLine;
if (!ts->srcCoords.isOnThisLine(offset, currentLine(), &onThisLine))
return ts->reportError(JSMSG_OUT_OF_MEMORY);
if (!onThisLine) {
unsigned line = ts->srcCoords.lineNum(offset);
unsigned delta = line - currentLine();

View File

@ -1971,7 +1971,8 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
// while LazyScript::{begin,end} offsets are relative to the outermost
// script source.
uint32_t userbufBase = lazyOuter->begin() - lazyOuter->column();
tokenStream.advance(fun->lazyScript()->end() - userbufBase);
if (!tokenStream.advance(fun->lazyScript()->end() - userbufBase))
return false;
*pbodyProcessed = true;
return true;

View File

@ -162,7 +162,7 @@ TokenStream::SourceCoords::SourceCoords(ExclusiveContext* cx, uint32_t ln)
lineStartOffsets_.infallibleAppend(maxPtr);
}
MOZ_ALWAYS_INLINE void
MOZ_ALWAYS_INLINE bool
TokenStream::SourceCoords::add(uint32_t lineNum, uint32_t lineStartOffset)
{
uint32_t lineIndex = lineNumToIndex(lineNum);
@ -171,21 +171,21 @@ TokenStream::SourceCoords::add(uint32_t lineNum, uint32_t lineStartOffset)
MOZ_ASSERT(lineStartOffsets_[0] == 0 && lineStartOffsets_[sentinelIndex] == MAX_PTR);
if (lineIndex == sentinelIndex) {
// We haven't seen this newline before. Update lineStartOffsets_.
// We ignore any failures due to OOM -- because we always have a
// sentinel node, it'll just be like the newline wasn't present. I.e.
// the line numbers will be wrong, but the code won't crash or anything
// like that.
lineStartOffsets_[lineIndex] = lineStartOffset;
// We haven't seen this newline before. Update lineStartOffsets_
// only if lineStartOffsets_.append succeeds, to keep sentinel.
// Otherwise return false to tell TokenStream about OOM.
uint32_t maxPtr = MAX_PTR;
(void)lineStartOffsets_.append(maxPtr);
if (!lineStartOffsets_.append(maxPtr))
return false;
lineStartOffsets_[lineIndex] = lineStartOffset;
} else {
// We have seen this newline before (and ungot it). Do nothing (other
// than checking it hasn't mysteriously changed).
MOZ_ASSERT(lineStartOffsets_[lineIndex] == lineStartOffset);
// This path can be executed after hitting OOM, so check lineIndex.
MOZ_ASSERT_IF(lineIndex < sentinelIndex, lineStartOffsets_[lineIndex] == lineStartOffset);
}
return true;
}
MOZ_ALWAYS_INLINE bool
@ -360,7 +360,8 @@ TokenStream::updateLineInfoForEOL()
prevLinebase = linebase;
linebase = userbuf.offset();
lineno++;
srcCoords.add(lineno, linebase);
if (!srcCoords.add(lineno, linebase))
flags.hitOOM = true;
}
MOZ_ALWAYS_INLINE void
@ -493,7 +494,7 @@ TokenStream::TokenBuf::findEOLMax(size_t start, size_t max)
return start + n;
}
void
bool
TokenStream::advance(size_t position)
{
const char16_t* end = userbuf.rawCharPtrAt(position);
@ -504,6 +505,11 @@ TokenStream::advance(size_t position)
cur->pos.begin = userbuf.offset();
MOZ_MAKE_MEM_UNDEFINED(&cur->type, sizeof(cur->type));
lookahead = 0;
if (flags.hitOOM)
return reportError(JSMSG_OUT_OF_MEMORY);
return true;
}
void
@ -1631,6 +1637,9 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
MOZ_CRASH("should have jumped to |out| or |error|");
out:
if (flags.hitOOM)
return reportError(JSMSG_OUT_OF_MEMORY);
flags.isDirtyLine = true;
tp->pos.end = userbuf.offset();
MOZ_ASSERT(IsTokenSane(tp));
@ -1638,6 +1647,9 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
return true;
error:
if (flags.hitOOM)
return reportError(JSMSG_OUT_OF_MEMORY);
flags.isDirtyLine = true;
tp->pos.end = userbuf.offset();
MOZ_MAKE_MEM_UNDEFINED(&tp->type, sizeof(tp->type));

View File

@ -351,9 +351,10 @@ class MOZ_STACK_CLASS TokenStream
bool sawOctalEscape:1; // Saw an octal character escape.
bool hadError:1; // Hit a syntax error, at start or during a
// token.
bool hitOOM:1; // Hit OOM.
Flags()
: isEOF(), isDirtyLine(), sawOctalEscape(), hadError()
: isEOF(), isDirtyLine(), sawOctalEscape(), hadError(), hitOOM()
{}
};
@ -435,11 +436,16 @@ class MOZ_STACK_CLASS TokenStream
// it's the same as the line that the current token ends on, that's a
// stronger condition than what we are looking for, and we don't need
// to return TOK_EOL.
if (lookahead != 0 && srcCoords.isOnThisLine(curr.pos.end, lineno)) {
if (lookahead != 0) {
bool onThisLine;
if (!srcCoords.isOnThisLine(curr.pos.end, lineno, &onThisLine))
return reportError(JSMSG_OUT_OF_MEMORY);
if (onThisLine) {
MOZ_ASSERT(!flags.hadError);
*ttp = tokens[(cursor + 1) & ntokensMask].type;
return true;
}
}
// The above check misses two cases where we don't have to return
// TOK_EOL.
@ -525,7 +531,7 @@ class MOZ_STACK_CLASS TokenStream
Token lookaheadTokens[maxLookahead];
};
void advance(size_t position);
bool advance(size_t position);
void tell(Position*);
void seek(const Position& pos);
bool seek(const Position& pos, const TokenStream& other);
@ -626,14 +632,16 @@ class MOZ_STACK_CLASS TokenStream
public:
SourceCoords(ExclusiveContext* cx, uint32_t ln);
void add(uint32_t lineNum, uint32_t lineStartOffset);
bool add(uint32_t lineNum, uint32_t lineStartOffset);
bool fill(const SourceCoords& other);
bool isOnThisLine(uint32_t offset, uint32_t lineNum) const {
bool isOnThisLine(uint32_t offset, uint32_t lineNum, bool* onThisLine) const {
uint32_t lineIndex = lineNumToIndex(lineNum);
MOZ_ASSERT(lineIndex + 1 < lineStartOffsets_.length()); // +1 due to sentinel
return lineStartOffsets_[lineIndex] <= offset &&
if (lineIndex + 1 >= lineStartOffsets_.length()) // +1 due to sentinel
return false;
*onThisLine = lineStartOffsets_[lineIndex] <= offset &&
offset < lineStartOffsets_[lineIndex + 1];
return true;
}
uint32_t lineNum(uint32_t offset) const;