Browse files

Don't allow %> in regexes to work.

It's a pathological edge case, and makes <%= 10 / 2 %> much trickier.
I'm guessing that division is a more common use case than ejs parsers
for code in ejs templates.
  • Loading branch information...
1 parent 67cbbc4 commit 344da24bfb1c737bdeab78c4ea6e878b4def57f8 isaacs committed Jan 3, 2010
Showing with 77 additions and 50 deletions.
  1. +77 −50 lib/utils/ejs.js
View
127 lib/utils/ejs.js
@@ -75,21 +75,39 @@ function ejs_parseStr (src, filename) {
STATE_STR1 = "STATE_STR1",
STATE_STR2 = "STATE_STR2",
- STATE_NO_REGEX = "STATE_NO_REGEX",
- STATE_REGEX = "STATE_REGEX",
+ STATE_NO_COMMENT = "STATE_NO_COMMENT",
+ STATE_LINECOM = "STATE_LINECOM",
+ STATE_BLOCKCOM = "STATE_BLOCKCOM",
+ STATE_BLOCKCOM_STAR = "STATE_BLOCKCOM_STAR",
+
+ // STATE_NO_REGEX = "STATE_NO_REGEX",
+ // STATE_REGEX = "STATE_REGEX",
+
+ STATE_NO_SLASH = "STATE_NO_SLASH",
+ STATE_SLASH_START = "STATE_SLASH_START",
escaped = false,
state = STATE_HTML,
+ slash_state = STATE_NO_SLASH,
str_state = STATE_NO_STR,
- reg_state = STATE_NO_REGEX,
+ com_state = STATE_NO_COMMENT,
+ CHR_SLASH = "/",
CHR_STR1 = "'",
CHR_STR2 = '"',
CHR_OPEN = '<',
CHR_PCT = '%',
CHR_CLOSE = '>',
CHR_EQ = '=',
CHR_ESC = '\\',
+ CHR_STAR = "*",
+ CHR_CR = "\n",
+
+ STR_LINECOM_START = "//",
+ STR_LINECOM_END = CHR_CR,
+ STR_BLOCKCOM_START = "/*",
+ STR_BLOCKCOM_END = "*/",
+
STR_OPEN = "<%",
STR_PRINT = "<%=",
STR_CLOSE = "%>",
@@ -134,16 +152,13 @@ function ejs_parseStr (src, filename) {
html_buffer.pop();
}
// push the print statement onto the output buffer
- while (cr_count --> 0) out.push("\n");
- cr_count = 0;
+ while (--cr_count >= 0) out.push(CHR_CR);
if (html_buffer.length) {
out.push(';print(', JSON.stringify(html_buffer.join("")), ');');
}
html_buffer = [];
} else {
- if (c === "\n") {
- cr_count ++;
- }
+ if (c === CHR_CR) cr_count ++;
html_buffer.push(c);
}
} else if ( state === STATE_JS && c !== EOF ) {
@@ -160,49 +175,61 @@ function ejs_parseStr (src, filename) {
// push the print statement onto the buffer.
out.push("print(");
state = STATE_JS_PRINT;
- } else {
- // now it gets interesting.
- // we basically just need to watch for EOF or a %> that *isn't*
- // in a string or regex. When that happens, end the print() statement
- // if we're in STATE_JS_PRINT, and flip into STATE_HTML.
- if (str_state === STATE_STR1 && c !== EOF) {
- if (c === CHR_ESC || escaped) {
- escaped = !escaped;
- } else if ( c === CHR_STR1 ) {
- str_state = STATE_NO_STR;
- }
- out.push(c);
- } else if (str_state === STATE_STR2 && c !== EOF) {
- if (c === CHR_ESC || escaped) {
- escaped = !escaped;
- } else if ( c === CHR_STR2 ) {
- str_state = STATE_NO_STR;
- }
- out.push(c);
- } else if (reg_state === STATE_REGEX && c !== EOF) {
- if (c === CHR_ESC || escaped) {
- escaped = !escaped;
- } else if ( c === CHR_REG ) {
- reg_state = STATE_NO_REGEX;
- }
- out.push(c);
- } else {
- // not in a string or regexp.
- if (
- c === EOF ||
- c === CHR_CLOSE && out[out.length - 1] === CHR_PCT
- ) {
- if (c !== EOF) out.pop();
- if (state === STATE_JS_PRINT) {
- out.push(');');
- }
- state = STATE_HTML;
- str_state = STATE_NO_STR;
- reg_state = STATE_NO_REGEX;
- } else {
- out.push(c);
- }
+ } else if (str_state === STATE_STR1 && c !== EOF) {
+ if (c === CHR_ESC || escaped) {
+ escaped = !escaped;
+ } else if ( c === CHR_STR1 ) {
+ str_state = STATE_NO_STR;
+ }
+ out.push(c);
+ } else if (str_state === STATE_STR2 && c !== EOF) {
+ if (c === CHR_ESC || escaped) {
+ escaped = !escaped;
+ } else if ( c === CHR_STR2 ) {
+ str_state = STATE_NO_STR;
+ }
+ out.push(c);
+ } else if (com_state === STATE_LINECOM && c !== EOF) {
+ if (c === CHR_ESC || escaped) {
+ escaped = !escaped;
+ } else if (
+ c === CHR_CR
+ || c === CHR_CLOSE && out[out.length-1] === CHR_PCT
+ ) {
+ com_state = STATE_NO_COMMENT;
+ }
+ if (c === CHR_CR) out.push(c);
+ } else if (com_state === STATE_BLOCKCOM && c !== EOF) {
+ if (c === CHR_ESC || escaped) {
+ escaped = !escaped;
+ } else if (c === CHR_SLASH && out[out.length-1] == CHR_STAR) {
+ com_state = STATE_NO_COMMENT;
+ }
+ out.push(c);
+ } else if (slash_state === STATE_SLASH_START) {
+ slash_state = STATE_NO_SLASH;
+ if (c === CHR_SLASH) {
+ com_state = STATE_LINECOM;
+ } else if (c === CHR_STAR) {
+ com_state = STATE_BLOCKCOM;
}
+ if (c !== EOF) out.push(c);
+ } else if (c === CHR_SLASH) {
+ if (escaped) escaped = !escaped;
+ else slash_state = STATE_SLASH_START;
+ out.push(c);
+ } else if (
+ c === EOF ||
+ c === CHR_CLOSE && out[out.length - 1] === CHR_PCT
+ ) {
+ if (c !== EOF) out.pop();
+ if (state === STATE_JS_PRINT) {
+ out.push(');');
+ }
+ state = STATE_HTML;
+ str_state = STATE_NO_STR;
+ } else {
+ out.push(c);
}
} // end for
out.push(FINISH);

0 comments on commit 344da24

Please sign in to comment.