summaryrefslogtreecommitdiffstats
path: root/js/src/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/frontend')
-rw-r--r--js/src/frontend/TokenStream.cpp55
-rw-r--r--js/src/frontend/TokenStream.h8
2 files changed, 45 insertions, 18 deletions
diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp
index abb7228eb..6c5ea8fe9 100644
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -968,7 +968,6 @@ TokenStream::getDirective(bool isMultiline, bool shouldWarnDeprecated,
{
MOZ_ASSERT(directiveLength <= 18);
char16_t peeked[18];
- int32_t c;
if (peekChars(directiveLength, peeked) && CharsMatch(peeked, directive)) {
if (shouldWarnDeprecated) {
@@ -979,18 +978,33 @@ TokenStream::getDirective(bool isMultiline, bool shouldWarnDeprecated,
skipChars(directiveLength);
tokenbuf.clear();
- while ((c = peekChar()) && c != EOF && !unicode::IsSpaceOrBOM2(c)) {
- getChar();
+ do {
+ int32_t c;
+ if (!peekChar(&c))
+ return false;
+
+ if (c == EOF || unicode::IsSpaceOrBOM2(c))
+ break;
+
+ consumeKnownChar(c);
+
// Debugging directives can occur in both single- and multi-line
// comments. If we're currently inside a multi-line comment, we also
// need to recognize multi-line comment terminators.
- if (isMultiline && c == '*' && peekChar() == '/') {
- ungetChar('*');
- break;
+ if (isMultiline && c == '*') {
+ int32_t c2;
+ if (!peekChar(&c2))
+ return false;
+
+ if (c2 == '/') {
+ ungetChar('*');
+ break;
+ }
}
+
if (!tokenbuf.append(c))
return false;
- }
+ } while (true);
if (tokenbuf.empty()) {
// The directive's URL was missing, but this is not quite an
@@ -1722,7 +1736,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
case '/':
// Look for a single-line comment.
if (matchChar('/')) {
- c = peekChar();
+ if (!peekChar(&c))
+ goto error;
if (c == '@' || c == '#') {
bool shouldWarn = getChar() == '@';
if (!getDirectives(false, shouldWarn))
@@ -1789,7 +1804,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
RegExpFlag reflags = NoFlags;
unsigned length = tokenbuf.length() + 1;
while (true) {
- c = peekChar();
+ if (!peekChar(&c))
+ goto error;
if (c == 'g' && !(reflags & GlobalFlag))
reflags = RegExpFlag(reflags | GlobalFlag);
else if (c == 'i' && !(reflags & IgnoreCaseFlag))
@@ -1806,7 +1822,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
length++;
}
- c = peekChar();
+ if (!peekChar(&c))
+ goto error;
if (JS7_ISLET(c)) {
char buf[2] = { '\0', '\0' };
tp->pos.begin += length + 1;
@@ -1829,8 +1846,13 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
case '-':
if (matchChar('-')) {
- if (peekChar() == '>' && !flags.isDirtyLine)
+ int32_t c2;
+ if (!peekChar(&c2))
+ goto error;
+
+ if (c2 == '>' && !flags.isDirtyLine)
goto skipline;
+
tp->type = TOK_DEC;
} else {
tp->type = matchChar('=') ? TOK_SUBASSIGN : TOK_SUB;
@@ -1884,7 +1906,10 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
bool
TokenStream::matchBracedUnicode(bool* matched, uint32_t* cp)
{
- if (peekChar() != '{') {
+ int32_t c;
+ if (!peekChar(&c))
+ return false;
+ if (c != '{') {
*matched = false;
return true;
}
@@ -2015,7 +2040,8 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
if (JS7_ISOCT(c)) {
int32_t val = JS7_UNOCT(c);
- c = peekChar();
+ if (!peekChar(&c))
+ return false;
// Strict mode code allows only \0, then a non-digit.
if (val != 0 || JS7_ISDEC(c)) {
@@ -2031,7 +2057,8 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
if (JS7_ISOCT(c)) {
val = 8 * val + JS7_UNOCT(c);
getChar();
- c = peekChar();
+ if (!peekChar(&c))
+ return false;
if (JS7_ISOCT(c)) {
int32_t save = val;
val = 8 * val + JS7_UNOCT(c);
diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h
index 19385b499..e0e4b959e 100644
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -990,10 +990,10 @@ class MOZ_STACK_CLASS TokenStream
MOZ_ASSERT(c == expect);
}
- int32_t peekChar() {
- int32_t c = getChar();
- ungetChar(c);
- return c;
+ MOZ_MUST_USE bool peekChar(int32_t* c) {
+ *c = getChar();
+ ungetChar(*c);
+ return true;
}
void skipChars(int n) {