diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-09-20 15:56:39 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-09-20 15:56:39 -0300 |
commit | 20d42ccaaed9a84783d548d76633a5a38f0091f1 (patch) | |
tree | 4d0aae4dfac41956ac35a69ece27d042acd8f4f8 | |
parent | 70d6975018c1f2b8ce34058a4d54a28a3fafca66 (diff) | |
download | lua-20d42ccaaed9a84783d548d76633a5a38f0091f1.tar.gz lua-20d42ccaaed9a84783d548d76633a5a38f0091f1.tar.bz2 lua-20d42ccaaed9a84783d548d76633a5a38f0091f1.zip |
No errors in 'luaO_pushvfstring'
Any call to 'va_start' must have a corresponding call to 'va_end';
so, functions called between them (luaO_pushvfstring in particular)
cannot raise errors.
-rw-r--r-- | lapi.c | 2 | ||||
-rw-r--r-- | lauxlib.c | 2 | ||||
-rw-r--r-- | ldebug.c | 3 | ||||
-rw-r--r-- | lobject.c | 37 | ||||
-rw-r--r-- | manual/manual.of | 25 |
5 files changed, 45 insertions, 24 deletions
@@ -587,6 +587,8 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { | |||
587 | ret = luaO_pushvfstring(L, fmt, argp); | 587 | ret = luaO_pushvfstring(L, fmt, argp); |
588 | va_end(argp); | 588 | va_end(argp); |
589 | luaC_checkGC(L); | 589 | luaC_checkGC(L); |
590 | if (ret == NULL) /* error? */ | ||
591 | luaD_throw(L, LUA_ERRMEM); | ||
590 | lua_unlock(L); | 592 | lua_unlock(L); |
591 | return ret; | 593 | return ret; |
592 | } | 594 | } |
@@ -225,7 +225,7 @@ LUALIB_API void luaL_where (lua_State *L, int level) { | |||
225 | /* | 225 | /* |
226 | ** Again, the use of 'lua_pushvfstring' ensures this function does | 226 | ** Again, the use of 'lua_pushvfstring' ensures this function does |
227 | ** not need reserved stack space when called. (At worst, it generates | 227 | ** not need reserved stack space when called. (At worst, it generates |
228 | ** an error with "stack overflow" instead of the given message.) | 228 | ** a memory error instead of the given message.) |
229 | */ | 229 | */ |
230 | LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { | 230 | LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { |
231 | va_list argp; | 231 | va_list argp; |
@@ -847,7 +847,8 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { | |||
847 | va_start(argp, fmt); | 847 | va_start(argp, fmt); |
848 | msg = luaO_pushvfstring(L, fmt, argp); /* format message */ | 848 | msg = luaO_pushvfstring(L, fmt, argp); /* format message */ |
849 | va_end(argp); | 849 | va_end(argp); |
850 | if (isLua(ci)) { /* if Lua function, add source:line information */ | 850 | if (msg != NULL && isLua(ci)) { /* Lua function? (and no error) */ |
851 | /* add source:line information */ | ||
851 | luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); | 852 | luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); |
852 | setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ | 853 | setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ |
853 | L->top.p--; | 854 | L->top.p--; |
@@ -480,7 +480,7 @@ void luaO_tostring (lua_State *L, TValue *obj) { | |||
480 | #define BUFVFS cast_uint(LUA_IDSIZE + MAXNUMBER2STR + 95) | 480 | #define BUFVFS cast_uint(LUA_IDSIZE + MAXNUMBER2STR + 95) |
481 | 481 | ||
482 | /* | 482 | /* |
483 | ** Buffer used by 'luaO_pushvfstring'. 'err' signals any error while | 483 | ** Buffer used by 'luaO_pushvfstring'. 'err' signals an error while |
484 | ** building result (memory error [1] or buffer overflow [2]). | 484 | ** building result (memory error [1] or buffer overflow [2]). |
485 | */ | 485 | */ |
486 | typedef struct BuffFS { | 486 | typedef struct BuffFS { |
@@ -512,9 +512,14 @@ static void pushbuff (lua_State *L, void *ud) { | |||
512 | case 1: | 512 | case 1: |
513 | luaD_throw(L, LUA_ERRMEM); | 513 | luaD_throw(L, LUA_ERRMEM); |
514 | break; | 514 | break; |
515 | case 2: | 515 | case 2: /* length overflow: Add "..." at the end of result */ |
516 | luaG_runerror(L, "buffer overflow"); | 516 | if (buff->buffsize - buff->blen < 3) |
517 | break; | 517 | strcpy(buff->b + buff->blen - 3, "..."); /* 'blen' must be > 3 */ |
518 | else { /* there is enough space left for the "..." */ | ||
519 | strcpy(buff->b + buff->blen, "..."); | ||
520 | buff->blen += 3; | ||
521 | } | ||
522 | /* FALLTHROUGH */ | ||
518 | default: { /* no errors */ | 523 | default: { /* no errors */ |
519 | TString *ts = luaS_newlstr(L, buff->b, buff->blen); | 524 | TString *ts = luaS_newlstr(L, buff->b, buff->blen); |
520 | setsvalue2s(L, L->top.p, ts); | 525 | setsvalue2s(L, L->top.p, ts); |
@@ -527,8 +532,10 @@ static void pushbuff (lua_State *L, void *ud) { | |||
527 | static const char *clearbuff (BuffFS *buff) { | 532 | static const char *clearbuff (BuffFS *buff) { |
528 | lua_State *L = buff->L; | 533 | lua_State *L = buff->L; |
529 | const char *res; | 534 | const char *res; |
530 | pushbuff(L, buff); | 535 | if (luaD_rawrunprotected(L, pushbuff, buff) != LUA_OK) /* errors? */ |
531 | res = getstr(tsvalue(s2v(L->top.p - 1))); | 536 | res = NULL; /* error message is on the top of the stack */ |
537 | else | ||
538 | res = getstr(tsvalue(s2v(L->top.p - 1))); | ||
532 | if (buff->b != buff->space) /* using dynamic buffer? */ | 539 | if (buff->b != buff->space) /* using dynamic buffer? */ |
533 | luaM_freearray(L, buff->b, buff->buffsize); /* free it */ | 540 | luaM_freearray(L, buff->b, buff->buffsize); /* free it */ |
534 | return res; | 541 | return res; |
@@ -536,12 +543,14 @@ static const char *clearbuff (BuffFS *buff) { | |||
536 | 543 | ||
537 | 544 | ||
538 | static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { | 545 | static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { |
546 | size_t left = buff->buffsize - buff->blen; /* space left in the buffer */ | ||
539 | if (buff->err) /* do nothing else after an error */ | 547 | if (buff->err) /* do nothing else after an error */ |
540 | return; | 548 | return; |
541 | if (slen > buff->buffsize - buff->blen) { | 549 | if (slen > left) { /* new string doesn't fit into current buffer? */ |
542 | /* new string doesn't fit into current buffer */ | ||
543 | if (slen > ((MAX_SIZE/2) - buff->blen)) { /* overflow? */ | 550 | if (slen > ((MAX_SIZE/2) - buff->blen)) { /* overflow? */ |
544 | buff->err = 2; | 551 | memcpy(buff->b + buff->blen, str, left); /* copy what it can */ |
552 | buff->blen = buff->buffsize; | ||
553 | buff->err = 2; /* doesn't add anything else */ | ||
545 | return; | 554 | return; |
546 | } | 555 | } |
547 | else { | 556 | else { |
@@ -552,13 +561,13 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { | |||
552 | : luaM_reallocvector(buff->L, buff->b, buff->buffsize, newsize, | 561 | : luaM_reallocvector(buff->L, buff->b, buff->buffsize, newsize, |
553 | char); | 562 | char); |
554 | if (newb == NULL) { /* allocation error? */ | 563 | if (newb == NULL) { /* allocation error? */ |
555 | buff->err = 1; | 564 | buff->err = 1; /* signal a memory error */ |
556 | return; | 565 | return; |
557 | } | 566 | } |
558 | if (buff->b == buff->space) | 567 | if (buff->b == buff->space) /* new buffer (not reallocated)? */ |
559 | memcpy(newb, buff->b, buff->blen); /* copy previous content */ | 568 | memcpy(newb, buff->b, buff->blen); /* copy previous content */ |
560 | buff->b = newb; | 569 | buff->b = newb; /* set new (larger) buffer... */ |
561 | buff->buffsize = newsize; | 570 | buff->buffsize = newsize; /* ...and its new size */ |
562 | } | 571 | } |
563 | } | 572 | } |
564 | memcpy(buff->b + buff->blen, str, slen); /* copy new content */ | 573 | memcpy(buff->b + buff->blen, str, slen); /* copy new content */ |
@@ -651,6 +660,8 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { | |||
651 | va_start(argp, fmt); | 660 | va_start(argp, fmt); |
652 | msg = luaO_pushvfstring(L, fmt, argp); | 661 | msg = luaO_pushvfstring(L, fmt, argp); |
653 | va_end(argp); | 662 | va_end(argp); |
663 | if (msg == NULL) /* error? */ | ||
664 | luaD_throw(L, LUA_ERRMEM); | ||
654 | return msg; | 665 | return msg; |
655 | } | 666 | } |
656 | 667 | ||
diff --git a/manual/manual.of b/manual/manual.of index f0a2ed94..1ac537f7 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
@@ -3974,7 +3974,7 @@ Lua will call @id{falloc} before raising the error. | |||
3974 | 3974 | ||
3975 | 3975 | ||
3976 | @APIEntry{const char *lua_pushfstring (lua_State *L, const char *fmt, ...);| | 3976 | @APIEntry{const char *lua_pushfstring (lua_State *L, const char *fmt, ...);| |
3977 | @apii{0,1,v} | 3977 | @apii{0,1,m} |
3978 | 3978 | ||
3979 | Pushes onto the stack a formatted string | 3979 | Pushes onto the stack a formatted string |
3980 | and returns a pointer to this string @see{constchar}. | 3980 | and returns a pointer to this string @see{constchar}. |
@@ -3997,9 +3997,6 @@ The conversion specifiers can only be | |||
3997 | @Char{%c} (inserts an @T{int} as a one-byte character), and | 3997 | @Char{%c} (inserts an @T{int} as a one-byte character), and |
3998 | @Char{%U} (inserts an @T{unsigned long} as a @x{UTF-8} byte sequence). | 3998 | @Char{%U} (inserts an @T{unsigned long} as a @x{UTF-8} byte sequence). |
3999 | 3999 | ||
4000 | This function may raise errors due to memory overflow | ||
4001 | or an invalid conversion specifier. | ||
4002 | |||
4003 | } | 4000 | } |
4004 | 4001 | ||
4005 | @APIEntry{void lua_pushglobaltable (lua_State *L);| | 4002 | @APIEntry{void lua_pushglobaltable (lua_State *L);| |
@@ -4104,10 +4101,14 @@ onto the stack. | |||
4104 | const char *lua_pushvfstring (lua_State *L, | 4101 | const char *lua_pushvfstring (lua_State *L, |
4105 | const char *fmt, | 4102 | const char *fmt, |
4106 | va_list argp);| | 4103 | va_list argp);| |
4107 | @apii{0,1,v} | 4104 | @apii{0,1,-} |
4108 | 4105 | ||
4109 | Equivalent to @Lid{lua_pushfstring}, except that it receives a @id{va_list} | 4106 | Equivalent to @Lid{lua_pushfstring}, |
4110 | instead of a variable number of arguments. | 4107 | except that it receives a @id{va_list} |
4108 | instead of a variable number of arguments, | ||
4109 | and it does not raise errors. | ||
4110 | Instead, in case of errors it pushes the error message | ||
4111 | and returns @id{NULL}. | ||
4111 | 4112 | ||
4112 | } | 4113 | } |
4113 | 4114 | ||
@@ -5636,6 +5637,7 @@ It is defined as the following macro: | |||
5636 | } | 5637 | } |
5637 | It @N{returns 0} (@Lid{LUA_OK}) if there are no errors, | 5638 | It @N{returns 0} (@Lid{LUA_OK}) if there are no errors, |
5638 | or 1 in case of errors. | 5639 | or 1 in case of errors. |
5640 | (Except for out-of-memory errors, which are raised.) | ||
5639 | 5641 | ||
5640 | } | 5642 | } |
5641 | 5643 | ||
@@ -5800,7 +5802,7 @@ The first line in the file is ignored if it starts with a @T{#}. | |||
5800 | 5802 | ||
5801 | The string @id{mode} works as in the function @Lid{lua_load}. | 5803 | The string @id{mode} works as in the function @Lid{lua_load}. |
5802 | 5804 | ||
5803 | This function returns the same results as @Lid{lua_load} | 5805 | This function returns the same results as @Lid{lua_load}, |
5804 | or @Lid{LUA_ERRFILE} for file-related errors. | 5806 | or @Lid{LUA_ERRFILE} for file-related errors. |
5805 | 5807 | ||
5806 | As @Lid{lua_load}, this function only loads the chunk; | 5808 | As @Lid{lua_load}, this function only loads the chunk; |
@@ -9260,7 +9262,7 @@ the script is compiled as a variadic function. | |||
9260 | In interactive mode, | 9262 | In interactive mode, |
9261 | Lua repeatedly prompts and waits for a line. | 9263 | Lua repeatedly prompts and waits for a line. |
9262 | After reading a line, | 9264 | After reading a line, |
9263 | Lua first try to interpret the line as an expression. | 9265 | Lua first tries to interpret the line as an expression. |
9264 | If it succeeds, it prints its value. | 9266 | If it succeeds, it prints its value. |
9265 | Otherwise, it interprets the line as a chunk. | 9267 | Otherwise, it interprets the line as a chunk. |
9266 | If you write an incomplete chunk, | 9268 | If you write an incomplete chunk, |
@@ -9424,6 +9426,11 @@ instead, there is a new option @Lid{LUA_GCPARAM} to that end. | |||
9424 | Moreover, there were some changes in the parameters themselves. | 9426 | Moreover, there were some changes in the parameters themselves. |
9425 | } | 9427 | } |
9426 | 9428 | ||
9429 | @item{ | ||
9430 | The function @Lid{lua_pushvfstring} now reports errors, | ||
9431 | instead of raising them. | ||
9432 | } | ||
9433 | |||
9427 | } | 9434 | } |
9428 | 9435 | ||
9429 | } | 9436 | } |