@@ -91,6 +91,37 @@ tpl_term(int type, const char *str, size_t len, void *data)
91
91
}
92
92
}
93
93
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
+
94
125
static int
95
126
lbox_httpd_escape_html (struct lua_State * L )
96
127
{
@@ -109,11 +140,8 @@ lbox_httpd_escape_html(struct lua_State *L)
109
140
}
110
141
111
142
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 );
117
145
for (; * s ; s ++ ) {
118
146
switch (* s ) {
119
147
case '&' :
@@ -136,6 +164,7 @@ lbox_httpd_escape_html(struct lua_State *L)
136
164
break ;
137
165
}
138
166
}
167
+ lua_remove (L , str_idx );
139
168
}
140
169
141
170
luaL_pushresult (& b );
0 commit comments