@@ -91,6 +91,37 @@ tpl_term(int type, const char *str, size_t len, void *data)
9191 }
9292}
9393
94+ /**
95+ * This function exists because lua_tostring does not use
96+ * __tostring metamethod, and this metamethod has to be used
97+ * if we want to print Lua userdata correctly.
98+ */
99+ static const char *
100+ luaT_tolstring (lua_State * L , int idx , size_t * len )
101+ {
102+ if (!luaL_callmeta (L , idx , "__tostring" )) {
103+ switch (lua_type (L , idx )) {
104+ case LUA_TNUMBER :
105+ case LUA_TSTRING :
106+ lua_pushvalue (L , idx );
107+ break ;
108+ case LUA_TBOOLEAN : {
109+ int val = lua_toboolean (L , idx );
110+ lua_pushstring (L , val ? "true" : "false" );
111+ break ;
112+ }
113+ case LUA_TNIL :
114+ lua_pushliteral (L , "nil" );
115+ break ;
116+ default :
117+ lua_pushfstring (L , "%s: %p" , luaL_typename (L , idx ),
118+ lua_topointer (L , idx ));
119+ }
120+ }
121+
122+ return lua_tolstring (L , -1 , len );
123+ }
124+
94125static int
95126lbox_httpd_escape_html (struct lua_State * L )
96127{
@@ -109,11 +140,8 @@ lbox_httpd_escape_html(struct lua_State *L)
109140 }
110141
111142 for (i = 1 ; i <= top ; i ++ ) {
112- if (lua_isnil (L , i )) {
113- luaL_addstring (& b , "nil" );
114- continue ;
115- }
116- const char * s = lua_tostring (L , i );
143+ const char * s = luaT_tolstring (L , i , NULL );
144+ int str_idx = lua_gettop (L );
117145 for (; * s ; s ++ ) {
118146 switch (* s ) {
119147 case '&' :
@@ -136,6 +164,7 @@ lbox_httpd_escape_html(struct lua_State *L)
136164 break ;
137165 }
138166 }
167+ lua_remove (L , str_idx );
139168 }
140169
141170 luaL_pushresult (& b );
0 commit comments