aboutsummaryrefslogtreecommitdiff
path: root/lauxlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-13 13:50:33 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-13 13:50:33 -0200
commit8cb84210ab95e882c01363a6794508ec923ade90 (patch)
tree816598810dbf22e7bb119977863501edf067ffab /lauxlib.c
parent5fda30b4f9f82b901113a6e666c797f835c708eb (diff)
downloadlua-8cb84210ab95e882c01363a6794508ec923ade90.tar.gz
lua-8cb84210ab95e882c01363a6794508ec923ade90.tar.bz2
lua-8cb84210ab95e882c01363a6794508ec923ade90.zip
String buffer using to-be-closed variable
The string buffers in the C API now mark their boxes as to-be-closed variables, to release their buffers in case of errors.
Diffstat (limited to 'lauxlib.c')
-rw-r--r--lauxlib.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/lauxlib.c b/lauxlib.c
index 68842a98..6069ed1b 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -470,10 +470,8 @@ static void *resizebox (lua_State *L, int idx, size_t newsize) {
470 lua_Alloc allocf = lua_getallocf(L, &ud); 470 lua_Alloc allocf = lua_getallocf(L, &ud);
471 UBox *box = (UBox *)lua_touserdata(L, idx); 471 UBox *box = (UBox *)lua_touserdata(L, idx);
472 void *temp = allocf(ud, box->box, box->bsize, newsize); 472 void *temp = allocf(ud, box->box, box->bsize, newsize);
473 if (temp == NULL && newsize > 0) { /* allocation error? */ 473 if (temp == NULL && newsize > 0) /* allocation error? */
474 resizebox(L, idx, 0); /* free buffer */
475 luaL_error(L, "not enough memory for buffer allocation"); 474 luaL_error(L, "not enough memory for buffer allocation");
476 }
477 box->box = temp; 475 box->box = temp;
478 box->bsize = newsize; 476 box->bsize = newsize;
479 return temp; 477 return temp;
@@ -486,16 +484,20 @@ static int boxgc (lua_State *L) {
486} 484}
487 485
488 486
489static void *newbox (lua_State *L, size_t newsize) { 487static const luaL_Reg boxmt[] = { /* box metamethods */
488 {"__gc", boxgc},
489 {"__close", boxgc},
490 {NULL, NULL}
491};
492
493
494static void newbox (lua_State *L) {
490 UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0); 495 UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0);
491 box->box = NULL; 496 box->box = NULL;
492 box->bsize = 0; 497 box->bsize = 0;
493 if (luaL_newmetatable(L, "_UBOX*")) { /* creating metatable? */ 498 if (luaL_newmetatable(L, "_UBOX*")) /* creating metatable? */
494 lua_pushcfunction(L, boxgc); 499 luaL_setfuncs(L, boxmt, 0); /* set its metamethods */
495 lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */
496 }
497 lua_setmetatable(L, -2); 500 lua_setmetatable(L, -2);
498 return resizebox(L, -1, newsize);
499} 501}
500 502
501 503
@@ -536,9 +538,11 @@ static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) {
536 if (buffonstack(B)) /* buffer already has a box? */ 538 if (buffonstack(B)) /* buffer already has a box? */
537 newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */ 539 newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */
538 else { /* no box yet */ 540 else { /* no box yet */
539 newbuff = (char *)newbox(L, newsize); /* create a new box */ 541 newbox(L); /* create a new box */
540 memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */
541 lua_insert(L, boxidx); /* move box to its intended position */ 542 lua_insert(L, boxidx); /* move box to its intended position */
543 lua_toclose(L, boxidx);
544 newbuff = (char *)resizebox(L, boxidx, newsize);
545 memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */
542 } 546 }
543 B->b = newbuff; 547 B->b = newbuff;
544 B->size = newsize; 548 B->size = newsize;