Avoid using snprintf when MRB_DISABLE_STDIO is set; fix #4173

This commit is contained in:
Yukihiro "Matz" Matsumoto
2019-04-08 19:04:56 +09:00
parent 6cec0c9f62
commit ec1688807e
+68 -22
View File
@@ -220,6 +220,25 @@ parser_strdup(parser_state *p, const char *s)
#undef strdup
#define strdup(s) parser_strdup(p, s)
static void
itoa(short i, char *s)
{
char *p = s;
char *t = s;
while (i > 0) {
*p++ = (i % 10)+'0';
i /= 10;
}
if (p == s) *p++ = '0';
*p = 0;
p--; /* point the last char */
while (t < p) {
char c = *t;
*t++ = *p;
*p-- = c;
}
}
/* xxx ----------------------------- */
static node*
@@ -3172,7 +3191,7 @@ var_ref : variable
{
char buf[16];
snprintf(buf, sizeof(buf), "%d", p->lineno);
itoa(p->lineno, buf);
$$ = new_int(p, buf, 10);
}
| keyword__ENCODING__
@@ -3692,11 +3711,12 @@ yyerror(parser_state *p, const char *s)
}
static void
yyerror_i(parser_state *p, const char *fmt, int i)
yyerror_c(parser_state *p, const char *msg, char c)
{
char buf[256];
snprintf(buf, sizeof(buf), fmt, i);
strcpy(buf, msg);
strcat(buf, &c);
yyerror(p, buf);
}
@@ -3735,11 +3755,13 @@ yywarning(parser_state *p, const char *s)
}
static void
yywarning_s(parser_state *p, const char *fmt, const char *s)
yywarning_s(parser_state *p, const char *msg, const char *s)
{
char buf[256];
snprintf(buf, sizeof(buf), fmt, s);
strcpy(buf, msg);
strcat(buf, ": ");
strcat(buf, s);
yywarning(p, buf);
}
@@ -3751,10 +3773,10 @@ backref_error(parser_state *p, node *n)
c = intn(n->car);
if (c == NODE_NTH_REF) {
yyerror_i(p, "can't set variable $%" MRB_PRId, intn(n->cdr));
yyerror_c(p, "can't set variable $", (char)intn(n->cdr)+'0');
}
else if (c == NODE_BACK_REF) {
yyerror_i(p, "can't set variable $%c", intn(n->cdr));
yyerror_c(p, "can't set variable $", (char)intn(n->cdr));
}
else {
mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
@@ -4298,7 +4320,15 @@ parse_string(parser_state *p)
}
if (c < 0) {
char buf[256];
snprintf(buf, sizeof(buf), "can't find heredoc delimiter \"%s\" anywhere before EOF", hinf->term);
const char s1[] = "can't find heredoc delimiter \"";
const char s2[] = "\" anywhere before EOF";
if (sizeof(s1)+sizeof(s2)+strlen(hinf->term)+1 >= sizeof(buf)) {
yyerror(p, "can't find heredoc delimiter anywhere before EOF");
}
strcpy(buf, s1);
strcat(buf, hinf->term);
strcat(buf, s2);
yyerror(p, buf);
return 0;
}
@@ -4449,9 +4479,14 @@ parse_string(parser_state *p)
pushback(p, re_opt);
if (toklen(p)) {
char msg[128];
strcpy(msg, "unknown regexp option");
tokfix(p);
snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
toklen(p) > 1 ? "s" : "", tok(p));
if (toklen(p) > 1) {
strcat(msg, "s");
}
strcat(msg, " - ");
strcat(msg, tok(p));
yyerror(p, msg);
}
if (f != 0) {
@@ -4879,7 +4914,10 @@ parser_yylex(parser_state *p)
}
if (c2) {
char buf[256];
snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
char cc = (char)c2;
strcpy(buf, "invalid character syntax; use ?\\");
strcat(buf, &cc);
yyerror(p, buf);
}
}
@@ -5252,7 +5290,7 @@ parser_yylex(parser_state *p)
pushback(p, c);
if (nondigit) {
trailing_uc:
yyerror_i(p, "trailing '%c' in number", nondigit);
yyerror_c(p, "trailing non digit in number: ", (char)nondigit);
}
tokfix(p);
if (is_float) {
@@ -5267,10 +5305,10 @@ parser_yylex(parser_state *p)
errno = 0;
d = mrb_float_read(tok(p), &endp);
if (d == 0 && endp == tok(p)) {
yywarning_s(p, "corrupted float value %s", tok(p));
yywarning_s(p, "corrupted float value", tok(p));
}
else if (errno == ERANGE) {
yywarning_s(p, "float %s out of range", tok(p));
yywarning_s(p, "float out of range", tok(p));
errno = 0;
}
pylval.nd = new_float(p, tok(p));
@@ -5612,7 +5650,7 @@ parser_yylex(parser_state *p)
{
unsigned long n = strtoul(tok(p), NULL, 10);
if (n > INT_MAX) {
yyerror_i(p, "capture group index must be <= %d", INT_MAX);
yyerror(p, "capture group index must be <= " MRB_STRINGIZE(INT_MAX));
return 0;
}
pylval.nd = new_nth_ref(p, (int)n);
@@ -5649,10 +5687,10 @@ parser_yylex(parser_state *p)
}
else if (ISDIGIT(c)) {
if (p->tidx == 1) {
yyerror_i(p, "'@%c' is not allowed as an instance variable name", c);
yyerror_c(p, "wrong instance variable name: @", c);
}
else {
yyerror_i(p, "'@@%c' is not allowed as a class variable name", c);
yyerror_c(p, "wrong class variable name: @@", c);
}
return 0;
}
@@ -5668,7 +5706,14 @@ parser_yylex(parser_state *p)
default:
if (!identchar(c)) {
yyerror_i(p, "Invalid char '\\x%02X' in expression", c);
char buf[36];
const char s[] = "Invalid char in expression: 0x";
strcpy(buf, s);
buf[sizeof(s)] = (c & 0xff00) >> 8;
buf[sizeof(s)+1] = (c & 0xff);
buf[sizeof(s)+2] = 0;
yyerror(p, buf);
goto retry;
}
@@ -6097,11 +6142,12 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
if (c) c->parser_nerr = p->nerr;
if (p->capture_errors) {
char buf[256];
int n;
n = snprintf(buf, sizeof(buf), "line %d: %s\n",
p->error_buffer[0].lineno, p->error_buffer[0].message);
mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
strcpy(buf, "line ");
itoa(p->error_buffer[0].lineno, buf+5);
strcat(buf, ": ");
strcat(buf, p->error_buffer[0].message);
mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf)));
mrb_parser_free(p);
return mrb_undef_value();
}