summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2016-07-13 03:22:15 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2016-07-13 03:22:15 +0900
commitd4d807b774de0e776d2749acbcb22a1b38f1c50b (patch)
treee0b6c032d7e1584193f0d9b4f0a65515501d15ff
parent2e74a931121be3c1dbb030338527d301fec4d33f (diff)
downloadmruby-d4d807b774de0e776d2749acbcb22a1b38f1c50b.tar.gz
mruby-d4d807b774de0e776d2749acbcb22a1b38f1c50b.zip
relax string length limitation to 64KB; fix #2725
-rw-r--r--include/mruby/compile.h9
-rw-r--r--mrbgems/mruby-compiler/core/parse.y51
2 files changed, 41 insertions, 19 deletions
diff --git a/include/mruby/compile.h b/include/mruby/compile.h
index 633eb1b74..3ccaf9f6a 100644
--- a/include/mruby/compile.h
+++ b/include/mruby/compile.h
@@ -102,7 +102,8 @@ struct mrb_parser_heredoc_info {
mrb_ast_node *doc;
};
-#define MRB_PARSER_BUF_SIZE 1024
+#define MRB_PARSER_TOKBUF_MAX 65536
+#define MRB_PARSER_TOKBUF_SIZE 256
/* parser structure */
struct mrb_parser_state {
@@ -130,8 +131,10 @@ struct mrb_parser_state {
mrb_ast_node *locals;
mrb_ast_node *pb;
- char buf[MRB_PARSER_BUF_SIZE];
- int bidx;
+ char *tokbuf;
+ char buf[MRB_PARSER_TOKBUF_SIZE];
+ int tidx;
+ int tsiz;
mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
mrb_ast_node *heredocs_from_nextline;
diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y
index cdc4b41a7..155979baa 100644
--- a/mrbgems/mruby-compiler/core/parse.y
+++ b/mrbgems/mruby-compiler/core/parse.y
@@ -3573,7 +3573,12 @@ skips(parser_state *p, const char *s)
static int
newtok(parser_state *p)
{
- p->bidx = 0;
+ if (p->tokbuf != p->buf) {
+ mrb_free(p->mrb, p->tokbuf);
+ p->tokbuf = p->buf;
+ p->tsiz = MRB_PARSER_TOKBUF_SIZE;
+ }
+ p->tidx = 0;
return p->column - 1;
}
@@ -3581,7 +3586,7 @@ static void
tokadd(parser_state *p, int32_t c)
{
char utf8[4];
- unsigned len;
+ int i, len;
/* mrb_assert(-0x10FFFF <= c && c <= 0xFF); */
if (c >= 0) {
@@ -3615,42 +3620,51 @@ tokadd(parser_state *p, int32_t c)
len = 4;
}
}
- if (p->bidx+len <= MRB_PARSER_BUF_SIZE) {
- unsigned i;
- for (i = 0; i < len; i++) {
- p->buf[p->bidx++] = utf8[i];
+ if (p->tidx+len >= p->tsiz) {
+ if (p->tsiz >= MRB_PARSER_TOKBUF_MAX) {
+ p->tidx += len;
+ return;
+ }
+ p->tsiz *= 2;
+ if (p->tokbuf == p->buf) {
+ p->tokbuf = (char*)mrb_malloc(p->mrb, p->tsiz);
+ memcpy(p->tokbuf, p->buf, MRB_PARSER_TOKBUF_SIZE);
+ }
+ else {
+ p->tokbuf = (char*)mrb_realloc(p->mrb, p->tokbuf, p->tsiz);
}
}
+ for (i = 0; i < len; i++) {
+ p->tokbuf[p->tidx++] = utf8[i];
+ }
}
static int
toklast(parser_state *p)
{
- return p->buf[p->bidx-1];
+ return p->tokbuf[p->tidx-1];
}
static void
tokfix(parser_state *p)
{
- int i = p->bidx, imax = MRB_PARSER_BUF_SIZE - 1;
-
- if (i > imax) {
- i = imax;
+ if (p->tidx >= MRB_PARSER_TOKBUF_MAX) {
+ p->tidx = MRB_PARSER_TOKBUF_MAX-1;
yyerror(p, "string too long (truncated)");
}
- p->buf[i] = '\0';
+ p->tokbuf[p->tidx] = '\0';
}
static const char*
tok(parser_state *p)
{
- return p->buf;
+ return p->tokbuf;
}
static int
toklen(parser_state *p)
{
- return p->bidx;
+ return p->tidx;
}
#define IS_ARG() (p->lstate == EXPR_ARG || p->lstate == EXPR_CMDARG)
@@ -5196,7 +5210,7 @@ parser_yylex(parser_state *p)
c = nextc(p);
}
if (c < 0) {
- if (p->bidx == 1) {
+ if (p->tidx == 1) {
yyerror(p, "incomplete instance variable syntax");
}
else {
@@ -5205,7 +5219,7 @@ parser_yylex(parser_state *p)
return 0;
}
else if (isdigit(c)) {
- if (p->bidx == 1) {
+ if (p->tidx == 1) {
yyerror_i(p, "'@%c' is not allowed as an instance variable name", c);
}
else {
@@ -5486,6 +5500,8 @@ mrb_parser_new(mrb_state *mrb)
#if defined(PARSER_TEST) || defined(PARSER_DEBUG)
yydebug = 1;
#endif
+ p->tsiz = MRB_PARSER_TOKBUF_SIZE;
+ p->tokbuf = p->buf;
p->lex_strterm = NULL;
p->all_heredocs = p->parsing_heredoc = NULL;
@@ -5501,6 +5517,9 @@ mrb_parser_new(mrb_state *mrb)
MRB_API void
mrb_parser_free(parser_state *p) {
mrb_pool_close(p->pool);
+ if (p->tokbuf != p->buf) {
+ mrb_free(p->mrb, p->tokbuf);
+ }
}
MRB_API mrbc_context*