Przeglądaj źródła

String buffers, part 2f: Prevent self-put of buffer.

Sponsored by fmad.io.
Mike Pall 4 lat temu
rodzic
commit
a689e9dc43
3 zmienionych plików z 6 dodań i 1 usunięć
  1. 1 0
      src/lib_buffer.c
  2. 1 0
      src/lj_errmsg.h
  3. 4 1
      src/lj_strfmt.c

+ 1 - 0
src/lib_buffer.c

@@ -126,6 +126,7 @@ LJLIB_CF(buffer_method_put)
       lj_strfmt_putfnum((SBuf *)sbx, STRFMT_G14, numV(o));
     } else if (tvisbuf(o)) {
       SBufExt *sbx2 = bufV(o);
+      if (sbx2 == sbx) lj_err_arg(L, arg+1, LJ_ERR_BUFFER_SELF);
       lj_buf_putmem((SBuf *)sbx, sbx2->r, sbufxlen(sbx2));
     } else if (!mo && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
       /* Call __tostring metamethod inline. */

+ 1 - 0
src/lj_errmsg.h

@@ -182,6 +182,7 @@ ERRDEF(FFI_NYICALL,	"NYI: cannot call this C function (yet)")
 
 #if LJ_HASBUFFER
 /* String buffer errors. */
+ERRDEF(BUFFER_SELF,	"cannot put buffer into itself")
 ERRDEF(BUFFER_BADOPT,	"bad options table")
 ERRDEF(BUFFER_BADENC,	"cannot serialize " LUA_QS)
 ERRDEF(BUFFER_BADDEC,	"cannot deserialize tag 0x%02x")

+ 4 - 1
src/lj_strfmt.c

@@ -431,7 +431,7 @@ int lj_strfmt_putarg(lua_State *L, SBuf *sb, int arg, int retry)
 	MSize len;
 	const char *s;
 	cTValue *mo;
-	if (LJ_UNLIKELY(!tvisstr(o)) && retry >= 0 &&
+	if (LJ_UNLIKELY(!tvisstr(o) && !tvisbuf(o)) && retry >= 0 &&
 	    !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
 	  /* Call __tostring metamethod once. */
 	  copyTV(L, L->top++, mo);
@@ -447,10 +447,13 @@ int lj_strfmt_putarg(lua_State *L, SBuf *sb, int arg, int retry)
 	if (LJ_LIKELY(tvisstr(o))) {
 	  len = strV(o)->len;
 	  s = strVdata(o);
+#if LJ_HASBUFFER
 	} else if (tvisbuf(o)) {
 	  SBufExt *sbx = bufV(o);
+	  if (sbx == (SBufExt *)sb) lj_err_arg(L, arg+1, LJ_ERR_BUFFER_SELF);
 	  len = sbufxlen(sbx);
 	  s = sbx->r;
+#endif
 	} else {
 	  GCstr *str = lj_strfmt_obj(L, o);
 	  len = str->len;