Coverage Report

Created: 2025-01-28 06:44

/src/tarantool/src/box/lua/call.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above
9
 *    copyright notice, this list of conditions and the
10
 *    following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above
13
 *    copyright notice, this list of conditions and the following
14
 *    disclaimer in the documentation and/or other materials
15
 *    provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21
 * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
#include "box/box.h"
32
#include "box/lua/call.h"
33
#include "box/call.h"
34
#include "box/error.h"
35
#include "box/func.h"
36
#include "box/func_def.h"
37
#include "box/schema.h"
38
#include "fiber.h"
39
#include "tt_static.h"
40
41
#include "lua/utils.h"
42
#include "lua/serializer.h"
43
#include "lua/msgpack.h"
44
#include "lua/trigger.h"
45
46
#include "box/port.h"
47
#include "box/lua/misc.h"
48
#include "box/lua/tuple.h"
49
#include "small/obuf.h"
50
#include "trivia/util.h"
51
#include "mpstream/mpstream.h"
52
#include "box/session.h"
53
#include "box/iproto_features.h"
54
#include "core/mp_ctx.h"
55
56
/**
57
 * Handlers identifiers to obtain lua_Cfunction reference from
58
 * Lua registry table. These handlers are initialized on Tarantool
59
 * startup and are used until the Lua universe is destroyed.
60
 * Such approach reduces Lua GC usage since there is no need to
61
 * create short-lived GCfunc objects for the corresponding C
62
 * function on each iproto CALL/EVAL request or stored Lua
63
 * procedure call.
64
 */
65
enum handlers {
66
  HANDLER_CALL,
67
  HANDLER_CALL_BY_REF,
68
  HANDLER_ENCODE_CALL,
69
  HANDLER_ENCODE_CALL_16,
70
  HANDLER_EVAL,
71
  HANDLER_MAX,
72
};
73
74
static int execute_lua_refs[HANDLER_MAX];
75
76
/**
77
 * A copy of the default serializer with encode_error_as_ext option disabled.
78
 * Changes to the default serializer are propagated via an update trigger.
79
 * It is used for returning errors in the legacy format to clients that do
80
 * not support the MP_ERROR MsgPack extension.
81
 */
82
static struct luaL_serializer call_serializer_no_error_ext;
83
84
/**
85
 * Returns a serializer that should be used for encoding CALL/EVAL result.
86
 */
87
static struct luaL_serializer *
88
get_call_serializer(void)
89
0
{
90
0
  if (!iproto_features_test(&current_session()->meta.features,
91
0
          IPROTO_FEATURE_ERROR_EXTENSION)) {
92
0
    return &call_serializer_no_error_ext;
93
0
  } else {
94
0
    return luaL_msgpack_default;
95
0
  }
96
0
}
97
98
int
99
box_lua_find(lua_State *L, const char *name, const char *name_end)
100
0
{
101
0
  lua_checkstack(L, 2); /* No more than 2 entries are needed. */
102
0
  int top = lua_gettop(L);
103
104
  /* Take the first token. */
105
0
  const char *start = name;
106
0
  while (start != name_end && *start != '.' &&
107
0
         *start != ':' && *start != '[')
108
0
    start++;
109
0
  lua_pushlstring(L, name, start - name);
110
0
  lua_gettable(L, LUA_GLOBALSINDEX);
111
112
  /* Take the rest tokens. */
113
0
  while (start != name_end) {
114
0
    if (!lua_istable(L, -1) &&
115
0
        !lua_islightuserdata(L, -1) && !lua_isuserdata(L, -1))
116
0
      goto no_such_proc;
117
118
0
    char delim = *start++; /* skip delimiter. */
119
0
    if (delim == '.') {
120
      /* Look for the next token. */
121
0
      const char *end = start;
122
0
      while (end != name_end && *end != '.' &&
123
0
             *end != ':' && *end != '[')
124
0
        end++;
125
0
      lua_pushlstring(L, start, end - start);
126
0
      start = end;
127
0
    } else if (delim == ':') {
128
0
      lua_pushlstring(L, start, name_end - start);
129
0
      lua_gettable(L, -2); /* get function from object. */
130
0
      lua_insert(L, -2); /* swap function and object. */
131
0
      break;
132
0
    } else if (delim == '[') {
133
0
      const char *end = memchr(start, ']', name_end - start);
134
0
      if (end == NULL)
135
0
        goto no_such_proc;
136
137
0
      if (end - start >= 2 && start[0] == end[-1] &&
138
0
          (start[0] == '"' || start[0] == '\'')) {
139
        /* Quoted string, just extract it. */
140
0
        lua_pushlstring(L, start + 1, end - start - 2);
141
0
      } else {
142
        /* Must be a number, convert from string. */
143
0
        lua_pushlstring(L, start, end - start);
144
0
        int success;
145
0
        lua_Number num = lua_tonumberx(L, -1, &success);
146
0
        if (!success)
147
0
          goto no_such_proc;
148
0
        lua_pop(L, 1);
149
0
        lua_pushnumber(L, num);
150
0
      }
151
0
      start = end + 1; /* skip closing bracket. */
152
0
    } else {
153
0
      goto no_such_proc;
154
0
    }
155
156
0
    lua_gettable(L, -2); /* get child object from parent object. */
157
0
    lua_remove(L, -2); /* drop previous parent object. */
158
0
  }
159
160
  /* Now at top+1 must be the function, and at top+2 may be the object. */
161
0
  assert(lua_gettop(L) - top >= 1 && lua_gettop(L) - top <= 2);
162
0
  if (!lua_isfunction(L, top + 1) && !lua_istable(L, top + 1)) {
163
    /* lua_call or lua_gettable would raise a type error
164
     * for us, but our own message is more verbose. */
165
0
    goto no_such_proc;
166
0
  }
167
168
0
  return lua_gettop(L) - top;
169
170
0
no_such_proc:
171
0
  diag_set(ClientError, ER_NO_SUCH_PROC, tt_cstr(name, name_end - name));
172
0
  return -1;
173
0
}
174
175
/**
176
 * A helper to find lua stored procedures for box.call.
177
 * box.call iteslf is pure Lua, to avoid issues
178
 * with infinite call recursion smashing C
179
 * thread stack.
180
 */
181
182
static int
183
lbox_call_loadproc(struct lua_State *L)
184
0
{
185
0
  const char *name;
186
0
  size_t name_len;
187
0
  name = lua_tolstring(L, 1, &name_len);
188
0
  int count = box_lua_find(L, name, name + name_len);
189
0
  if (count < 0)
190
0
    return luaT_error(L);
191
0
  return count;
192
0
}
193
194
/*
195
 * Encode CALL_16 result.
196
 *
197
 * To allow clients to understand a complex return from
198
 * a procedure, we are compatible with SELECT protocol,
199
 * and return the number of return values first, and
200
 * then each return value as a tuple.
201
 *
202
 * The following conversion rules apply:
203
 *
204
 * If a Lua stack contains at least one scalar, each
205
 * value on the stack is converted to a tuple. A stack
206
 * containing a single Lua table with scalars is converted to
207
 * a tuple with multiple fields.
208
 *
209
 * If the stack is a Lua table, each member of which is
210
 * not scalar, each member of the table is converted to
211
 * a tuple. This way very large lists of return values can
212
 * be used, since Lua stack size is limited by 8000 elements,
213
 * while Lua table size is pretty much unlimited.
214
 *
215
 * Please read gh-291 carefully before "fixing" this code.
216
 */
217
static inline uint32_t
218
luamp_encode_call_16(lua_State *L, struct luaL_serializer *cfg,
219
         struct mpstream *stream)
220
0
{
221
0
  int nrets = lua_gettop(L);
222
0
  if (nrets == 0) {
223
0
    return 0;
224
0
  } else if (nrets > 1) {
225
    /*
226
     * Multireturn:
227
     * `return 1, box.tuple.new(...), array, 3, ...`
228
     */
229
0
    for (int i = 1; i <= nrets; ++i) {
230
0
      struct luaL_field field;
231
0
      if (luaL_tofield(L, cfg, i, &field) < 0)
232
0
        return luaT_error(L);
233
0
      struct tuple *tuple;
234
0
      if (field.type == MP_EXT &&
235
0
          (tuple = luaT_istuple(L, i)) != NULL) {
236
        /* `return ..., box.tuple.new(...), ...` */
237
0
        tuple_to_mpstream(tuple, stream);
238
0
      } else if (field.type != MP_ARRAY) {
239
        /*
240
         * `return ..., scalar, ... =>
241
         *         ..., { scalar }, ...`
242
         */
243
0
        lua_pushvalue(L, i);
244
0
        mpstream_encode_array(stream, 1);
245
0
        if (luamp_encode_r(L, cfg, stream, &field, 0) != 0)
246
0
          return luaT_error(L);
247
0
        lua_pop(L, 1);
248
0
      } else {
249
        /* `return ..., array, ...` */
250
0
        if (luamp_encode(L, cfg, stream, i) != 0)
251
0
          return luaT_error(L);
252
0
      }
253
0
    }
254
0
    return nrets;
255
0
  }
256
0
  assert(nrets == 1);
257
258
  /*
259
   * Inspect the first result
260
   */
261
0
  struct luaL_field root;
262
0
  if (luaL_tofield(L, cfg, 1, &root) < 0)
263
0
    return luaT_error(L);
264
0
  struct tuple *tuple;
265
0
  if (root.type == MP_EXT && (tuple = luaT_istuple(L, 1)) != NULL) {
266
    /* `return box.tuple()` */
267
0
    tuple_to_mpstream(tuple, stream);
268
0
    return 1;
269
0
  } else if (root.type != MP_ARRAY) {
270
    /*
271
     * `return scalar`
272
     * `return map`
273
     */
274
0
    mpstream_encode_array(stream, 1);
275
0
    assert(lua_gettop(L) == 1);
276
0
    if (luamp_encode_r(L, cfg, stream, &root, 0) != 0)
277
0
      return luaT_error(L);
278
0
    return 1;
279
0
  }
280
281
0
  assert(root.type == MP_ARRAY);
282
0
  if (root.size == 0) {
283
    /* `return {}` => `{ box.tuple() }` */
284
0
    mpstream_encode_array(stream, 0);
285
0
    return 1;
286
0
  }
287
288
  /* `return { tuple, scalar, tuple }` */
289
0
  assert(root.type == MP_ARRAY && root.size > 0);
290
0
  for (uint32_t t = 1; t <= root.size; t++) {
291
0
    lua_rawgeti(L, 1, t);
292
0
    struct luaL_field field;
293
0
    if (luaL_tofield(L, cfg, -1, &field) < 0)
294
0
      return luaT_error(L);
295
0
    if (field.type == MP_EXT && (tuple = luaT_istuple(L, -1))) {
296
0
      tuple_to_mpstream(tuple, stream);
297
0
    } else if (field.type != MP_ARRAY) {
298
      /* The first member of root table is not tuple/array */
299
0
      if (t == 1) {
300
        /*
301
         * `return { scalar, ... } =>
302
         *        box.tuple.new(scalar, ...)`
303
         */
304
0
        mpstream_encode_array(stream, root.size);
305
        /*
306
         * Encode the first field of tuple using
307
         * existing information from luaL_tofield
308
         */
309
0
        if (luamp_encode_r(L, cfg, stream, &field, 0) != 0)
310
0
          return luaT_error(L);
311
0
        lua_pop(L, 1);
312
0
        assert(lua_gettop(L) == 1);
313
        /* Encode remaining fields as usual */
314
0
        for (uint32_t f = 2; f <= root.size; f++) {
315
0
          lua_rawgeti(L, 1, f);
316
0
          if (luamp_encode(L, cfg, stream, -1) != 0)
317
0
            return luaT_error(L);
318
0
          lua_pop(L, 1);
319
0
        }
320
0
        return 1;
321
0
      }
322
      /*
323
       * `return { tuple/array, ..., scalar, ... } =>
324
       *         { tuple/array, ..., { scalar }, ... }`
325
       */
326
0
      mpstream_encode_array(stream, 1);
327
0
      if (luamp_encode_r(L, cfg, stream, &field, 0) != 0)
328
0
        return luaT_error(L);
329
330
0
    } else {
331
      /* `return { tuple/array, ..., tuple/array, ... }` */
332
0
      if (luamp_encode_r(L, cfg, stream, &field, 0) != 0)
333
0
        return luaT_error(L);
334
0
    }
335
0
    lua_pop(L, 1);
336
0
    assert(lua_gettop(L) == 1);
337
0
  }
338
0
  return root.size;
339
0
}
340
341
static const struct port_vtab port_lua_vtab;
342
343
void
344
port_lua_create_at(struct port *port, struct lua_State *L, int bottom)
345
0
{
346
0
  struct port_lua *port_lua = (struct port_lua *) port;
347
0
  memset(port_lua, 0, sizeof(*port_lua));
348
0
  port_lua->vtab = &port_lua_vtab;
349
0
  port_lua->L = L;
350
  /*
351
   * Allow to destroy the port even if no ref.
352
   * @Sa luaL_unref.
353
   */
354
0
  port_lua->ref = -1;
355
0
  port_lua->bottom = bottom;
356
0
}
357
358
bool
359
port_is_lua(struct port *port)
360
0
{
361
0
  return port->vtab == &port_lua_vtab;
362
0
}
363
364
struct execute_lua_ctx {
365
  int lua_ref;
366
  const char *name;
367
  uint32_t name_len;
368
  bool takes_raw_args;
369
  struct port *args;
370
};
371
372
static inline void
373
push_lua_args(lua_State *L, struct execute_lua_ctx *ctx)
374
0
{
375
0
  port_dump_lua(ctx->args, L, ctx->takes_raw_args ?
376
0
            PORT_DUMP_LUA_MODE_MP_OBJECT :
377
0
            PORT_DUMP_LUA_MODE_FLAT);
378
0
}
379
380
/**
381
 * Find a lua function by name and execute it. Used for body-less
382
 * UDFs, which may not yet be defined when a function definition
383
 * is loaded from _func table, or dynamically re-defined at any
384
 * time. We don't cache references to such functions.
385
 */
386
static int
387
execute_lua_call(lua_State *L)
388
0
{
389
0
  struct execute_lua_ctx *ctx =
390
0
    (struct execute_lua_ctx *) lua_topointer(L, 1);
391
0
  lua_settop(L, 0); /* clear the stack to simplify the logic below */
392
393
0
  const char *name = ctx->name;
394
0
  uint32_t name_len = ctx->name_len;
395
396
  /* How many objects are on stack after box_lua_find. */
397
0
  int oc = box_lua_find(L, name, name + name_len);
398
0
  if (oc < 0)
399
0
    return luaT_error(L);
400
401
  /* Push the rest of args (a tuple). */
402
0
  int top = lua_gettop(L);
403
0
  push_lua_args(L, ctx);
404
0
  int arg_count = lua_gettop(L) - top;
405
406
0
  lua_call(L, arg_count + oc - 1, LUA_MULTRET);
407
0
  return lua_gettop(L);
408
0
}
409
410
/**
411
 * Dereference a sandboxed function and execute it. Used for
412
 * persistent UDFs.
413
 */
414
static int
415
execute_lua_call_by_ref(lua_State *L)
416
0
{
417
0
  struct execute_lua_ctx *ctx =
418
0
    (struct execute_lua_ctx *) lua_topointer(L, 1);
419
0
  lua_settop(L, 0); /* clear the stack to simplify the logic below */
420
421
0
  lua_rawgeti(L, LUA_REGISTRYINDEX, ctx->lua_ref);
422
423
  /* Push the rest of args (a tuple). */
424
0
  int top = lua_gettop(L);
425
0
  push_lua_args(L, ctx);
426
0
  int arg_count = lua_gettop(L) - top;
427
428
0
  lua_call(L, arg_count, LUA_MULTRET);
429
0
  return lua_gettop(L);
430
0
}
431
432
static int
433
execute_lua_eval(lua_State *L)
434
0
{
435
0
  struct execute_lua_ctx *ctx =
436
0
    (struct execute_lua_ctx *) lua_topointer(L, 1);
437
0
  lua_settop(L, 0); /* clear the stack to simplify the logic below */
438
439
  /* Compile expression */
440
0
  const char *expr = ctx->name;
441
0
  uint32_t expr_len = ctx->name_len;
442
0
  if (luaL_loadbuffer(L, expr, expr_len, "=eval")) {
443
0
    diag_set(LuajitError, lua_tostring(L, -1));
444
0
    luaT_error_at(L, 0);
445
0
  }
446
447
  /* Unpack arguments */
448
0
  int top = lua_gettop(L);
449
0
  push_lua_args(L, ctx);
450
0
  int arg_count = lua_gettop(L) - top;
451
452
  /* Call compiled code */
453
0
  lua_call(L, arg_count, LUA_MULTRET);
454
0
  return lua_gettop(L);
455
0
}
456
457
struct encode_lua_ctx {
458
  struct port_lua *port;
459
  struct mpstream *stream;
460
  /** MsgPack encoding context to save meta information to. */
461
  struct mp_ctx *mp_ctx;
462
};
463
464
/**
465
 * Encode call results to msgpack from Lua stack.
466
 * Lua stack has the following structure -- the last element is
467
 * lightuserdata pointer to encode_lua_ctx, all other values are
468
 * arguments to process.
469
 * The function encodes all given Lua objects to msgpack stream
470
 * from context, sets port's size and returns no value on the Lua
471
 * stack.
472
 * XXX: This function *MUST* be called under lua_pcall(), because
473
 * luamp_encode() may raise an error.
474
 */
475
static int
476
encode_lua_call(lua_State *L)
477
0
{
478
0
  assert(lua_islightuserdata(L, -1));
479
0
  struct encode_lua_ctx *encode_lua_ctx =
480
0
    (struct encode_lua_ctx *) lua_topointer(L, -1);
481
0
  assert(encode_lua_ctx->port->L == L);
482
  /* Delete ctx from the stack. */
483
0
  lua_pop(L, 1);
484
  /*
485
   * Add all elements from Lua stack to the buffer.
486
   *
487
   * TODO: forbid explicit yield from __serialize or __index here
488
   */
489
0
  struct luaL_serializer *cfg = get_call_serializer();
490
0
  const int size = lua_gettop(L);
491
0
  for (int i = 1; i <= size; ++i) {
492
0
    if (luamp_encode_with_ctx(L, cfg, encode_lua_ctx->stream, i,
493
0
            encode_lua_ctx->mp_ctx, NULL) != 0)
494
0
      return luaT_error(L);
495
0
  }
496
0
  encode_lua_ctx->port->size = size;
497
0
  mpstream_flush(encode_lua_ctx->stream);
498
0
  return 0;
499
0
}
500
501
/**
502
 * Encode call_16 results to msgpack from Lua stack.
503
 * Lua stack has the following structure -- the last element is
504
 * lightuserdata pointer to encode_lua_ctx, all other values are
505
 * arguments to process.
506
 * The function encodes all given Lua objects to msgpack stream
507
 * from context, sets port's size and returns no value on the Lua
508
 * stack.
509
 * XXX: This function *MUST* be called under lua_pcall(), because
510
 * luamp_encode() may raise an error.
511
 */
512
static int
513
encode_lua_call_16(lua_State *L)
514
0
{
515
0
  assert(lua_islightuserdata(L, -1));
516
0
  struct encode_lua_ctx *ctx =
517
0
    (struct encode_lua_ctx *) lua_topointer(L, -1);
518
0
  assert(ctx->port->L == L);
519
  /* Delete ctx from the stack. */
520
0
  lua_pop(L, 1);
521
  /*
522
   * Add all elements from Lua stack to the buffer.
523
   *
524
   * TODO: forbid explicit yield from __serialize or __index here
525
   */
526
0
  struct luaL_serializer *cfg = get_call_serializer();
527
0
  ctx->port->size = luamp_encode_call_16(L, cfg, ctx->stream);
528
0
  mpstream_flush(ctx->stream);
529
0
  return 0;
530
0
}
531
532
/**
533
 * Get port contents as raw MsgPack. Encodes the port's Lua values on
534
 * the current fiber's region using a MsgPack stream.
535
 */
536
static const char *
537
port_lua_get_msgpack(struct port *base, uint32_t *size);
538
539
static inline int
540
port_lua_do_dump_with_ctx(struct port *base, struct mpstream *stream,
541
        enum handlers handler, struct mp_ctx *mp_ctx)
542
0
{
543
0
  struct port_lua *port = (struct port_lua *) base;
544
0
  assert(port->vtab == &port_lua_vtab);
545
  /*
546
   * Use the same global state, assuming the encoder doesn't
547
   * yield.
548
   */
549
0
  struct encode_lua_ctx encode_lua_ctx = {
550
0
    .port = port,
551
0
    .stream = stream,
552
0
    .mp_ctx = mp_ctx,
553
0
  };
554
0
  lua_State *L = port->L;
555
  /*
556
   * At the moment Lua stack holds only values to encode.
557
   * Push corresponding encoder, push duplicates of values
558
   * so that the port can be dumped multiple times and push
559
   * encode context as lightuserdata to the top.
560
   */
561
0
  const int size = lua_gettop(L) - port->bottom + 1;
562
0
  lua_rawgeti(L, LUA_REGISTRYINDEX, execute_lua_refs[handler]);
563
0
  assert(lua_isfunction(L, -1) && lua_iscfunction(L, -1));
564
0
  for (int i = 0; i < size; i++)
565
0
    lua_pushvalue(L, port->bottom + i);
566
0
  lua_pushlightuserdata(L, &encode_lua_ctx);
567
  /* nargs -- all arguments + lightuserdata. */
568
0
  if (luaT_call(L, size + 1, 0) != 0)
569
0
    return -1;
570
0
  return port->size;
571
0
}
572
573
static inline int
574
port_lua_do_dump(struct port *base, struct mpstream *stream,
575
     enum handlers handler)
576
0
{
577
0
  return port_lua_do_dump_with_ctx(base, stream, handler, NULL);
578
0
}
579
580
/**
581
 * Dump Lua port contents to output buffer in MsgPack format.
582
 */
583
static int
584
port_lua_dump(struct port *base, struct obuf *out, struct mp_ctx *ctx)
585
0
{
586
0
  struct port_lua *port = (struct port_lua *) base;
587
0
  struct mpstream stream;
588
0
  mpstream_init(&stream, out, obuf_reserve_cb, obuf_alloc_cb,
589
0
          luamp_error, port->L);
590
0
  return port_lua_do_dump_with_ctx(base, &stream, HANDLER_ENCODE_CALL,
591
0
           ctx);
592
0
}
593
594
/**
595
 * Dump Lua port contents to output buffer in MsgPack format.
596
 */
597
static int
598
port_lua_dump_16(struct port *base, struct obuf *out, struct mp_ctx *ctx)
599
0
{
600
0
  struct port_lua *port = (struct port_lua *)base;
601
0
  struct mpstream stream;
602
0
  mpstream_init(&stream, out, obuf_reserve_cb, obuf_alloc_cb,
603
0
          luamp_error, port->L);
604
0
  return port_lua_do_dump_with_ctx(base, &stream, HANDLER_ENCODE_CALL_16,
605
0
           ctx);
606
0
}
607
608
/**
609
 * Dump port contents to Lua. Simply moves values from the Lua stack owned by
610
 * the port to the provided Lua stack.
611
 */
612
static void
613
port_lua_dump_lua(struct port *base, struct lua_State *L,
614
      enum port_dump_lua_mode mode)
615
0
{
616
0
  assert(mode == PORT_DUMP_LUA_MODE_FLAT ||
617
0
         mode == PORT_DUMP_LUA_MODE_MP_OBJECT);
618
0
  if (mode == PORT_DUMP_LUA_MODE_FLAT) {
619
0
    struct port_lua *port = (struct port_lua *)base;
620
0
    uint32_t size = lua_gettop(port->L) - port->bottom + 1;
621
    /*
622
     * Duplicate values so that the port can be dumped multiple
623
     * times.
624
     */
625
0
    for (size_t i = 0; i < size; i++)
626
0
      lua_pushvalue(port->L, port->bottom + i);
627
0
    lua_xmove(port->L, L, size);
628
0
    port->size = size;
629
0
  } else {
630
0
    port_dump_lua_mp_object_mode_slow(base, L, &fiber()->gc,
631
0
              port_lua_get_msgpack);
632
0
  }
633
0
}
634
635
static const char *
636
port_lua_get_msgpack(struct port *base, uint32_t *size)
637
0
{
638
0
  struct port_lua *port = (struct port_lua *) base;
639
0
  struct region *region = &fiber()->gc;
640
0
  uint32_t region_svp = region_used(region);
641
0
  struct mpstream stream;
642
0
  int port_size = lua_gettop(port->L) - port->bottom + 1;
643
0
  mpstream_init(&stream, region, region_reserve_cb, region_alloc_cb,
644
0
          luamp_error, port->L);
645
0
  mpstream_encode_array(&stream, port_size);
646
0
  int rc = port_lua_do_dump(base, &stream, HANDLER_ENCODE_CALL);
647
0
  if (rc < 0) {
648
0
    region_truncate(region, region_svp);
649
0
    return NULL;
650
0
  }
651
0
  *size = region_used(region) - region_svp;
652
0
  const char *data = region_join(region, *size);
653
0
  if (data == NULL) {
654
0
    diag_set(OutOfMemory, *size, "region", "data");
655
0
    region_truncate(region, region_svp);
656
0
    return NULL;
657
0
  }
658
0
  return data;
659
0
}
660
661
static void
662
port_lua_destroy(struct port *base)
663
0
{
664
0
  struct port_lua *port = (struct port_lua *)base;
665
0
  assert(port->vtab == &port_lua_vtab);
666
0
  lua_settop(port->L, port->bottom - 1);
667
0
  luaL_unref(tarantool_L, LUA_REGISTRYINDEX, port->ref);
668
0
}
669
670
/**
671
 * Dump port lua as a YAML document. It is extern since depends on
672
 * lyaml module.
673
 */
674
extern const char *
675
port_lua_dump_plain(struct port *port, uint32_t *size);
676
677
extern struct Mem *
678
port_lua_get_vdbemem(struct port *base, uint32_t *size);
679
680
const struct port_c_entry *
681
port_lua_get_c_entries(struct port *base)
682
0
{
683
0
  struct port_lua *port = (struct port_lua *)base;
684
0
  struct lua_State *L = port->L;
685
0
  size_t size = lua_gettop(L) - port->bottom + 1;
686
0
  if (size == 0)
687
0
    return NULL;
688
689
0
  struct port_c_entry *arr =
690
0
    xregion_alloc_array(&fiber()->gc, struct port_c_entry, size);
691
692
  /* Link the list. */
693
0
  for (size_t i = 0; i < size - 1; i++)
694
0
    arr[i].next = &arr[i + 1];
695
0
  arr[size - 1].next = NULL;
696
697
  /* Put values. */
698
0
  for (size_t arr_idx = 0; arr_idx < size; arr_idx++) {
699
0
    int lua_idx = arr_idx + port->bottom;
700
0
    struct port_c_entry *e = &arr[arr_idx];
701
0
    switch (lua_type(L, lua_idx)) {
702
0
    case LUA_TNIL:
703
0
      e->type = PORT_C_ENTRY_NULL;
704
0
      break;
705
0
    case LUA_TBOOLEAN:
706
0
      e->type = PORT_C_ENTRY_BOOL;
707
0
      e->boolean = lua_toboolean(L, lua_idx);
708
0
      break;
709
0
    case LUA_TNUMBER:
710
0
      e->type = PORT_C_ENTRY_NUMBER;
711
0
      e->number = lua_tonumber(L, lua_idx);
712
0
      break;
713
0
    case LUA_TSTRING: {
714
0
      e->type = PORT_C_ENTRY_STR;
715
0
      size_t len;
716
0
      const char *data = lua_tolstring(L, lua_idx, &len);
717
0
      e->str.data = data;
718
0
      e->str.size = len;
719
0
      break;
720
0
    }
721
0
    default: {
722
0
      struct tuple *tuple = NULL;
723
0
      tuple = luaT_istuple(L, lua_idx);
724
0
      if (tuple != NULL) {
725
0
        e->type = PORT_C_ENTRY_TUPLE;
726
0
        e->tuple = tuple;
727
        /*
728
         * Do not reference the tuple:
729
         * this entry does not own it.
730
         */
731
0
        break;
732
0
      }
733
734
0
      size_t len;
735
0
      const char *data = NULL;
736
0
      data = luamp_get(L, lua_idx, &len);
737
0
      if (data != NULL) {
738
0
        e->type = PORT_C_ENTRY_MP_OBJECT;
739
0
        e->mp.data = data;
740
0
        e->mp.size = len;
741
0
        e->mp.ctx = NULL;
742
0
        break;
743
0
      }
744
745
0
      if (luaL_isnull(L, lua_idx)) {
746
0
        e->type = PORT_C_ENTRY_NULL;
747
0
        break;
748
0
      }
749
750
      /* Unsupported value. */
751
0
      e->type = PORT_C_ENTRY_UNKNOWN;
752
0
    }
753
0
    }
754
0
  }
755
0
  return arr;
756
0
}
757
758
static const struct port_vtab port_lua_vtab = {
759
  .dump_msgpack = port_lua_dump,
760
  .dump_msgpack_16 = port_lua_dump_16,
761
  .dump_lua = port_lua_dump_lua,
762
  .dump_plain = port_lua_dump_plain,
763
  .get_msgpack = port_lua_get_msgpack,
764
  .get_vdbemem = port_lua_get_vdbemem,
765
  .get_c_entries = port_lua_get_c_entries,
766
  .destroy = port_lua_destroy,
767
};
768
769
static inline int
770
box_process_lua(enum handlers handler, struct execute_lua_ctx *ctx,
771
    struct port *ret)
772
0
{
773
0
  lua_State *L = luaT_newthread(tarantool_L);
774
0
  if (L == NULL)
775
0
    return -1;
776
0
  int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
777
0
  port_lua_create(ret, L);
778
0
  ((struct port_lua *) ret)->ref = coro_ref;
779
780
  /*
781
   * A code that need a temporary fiber-local Lua state may
782
   * save some time and resources for creating a new state
783
   * and use this one.
784
   */
785
0
  bool has_lua_stack = fiber()->storage.lua.stack != NULL;
786
0
  if (!has_lua_stack)
787
0
    fiber()->storage.lua.stack = L;
788
789
0
  lua_rawgeti(L, LUA_REGISTRYINDEX, execute_lua_refs[handler]);
790
0
  assert(lua_isfunction(L, -1));
791
0
  lua_pushlightuserdata(L, ctx);
792
0
  if (luaT_call(L, 1, LUA_MULTRET) != 0) {
793
0
    if (!has_lua_stack)
794
0
      fiber()->storage.lua.stack = NULL;
795
0
    port_lua_destroy(ret);
796
0
    return -1;
797
0
  }
798
799
  /*
800
   * Since this field is optional we're not obligated to
801
   * keep it until the Lua state will be unreferenced in
802
   * port_lua_destroy().
803
   *
804
   * There is no much sense to keep it beyond the Lua call,
805
   * so let's zap now.
806
   *
807
   * But: keep the stack if it was present before the call,
808
   * because it would be counter-intuitive if the existing
809
   * state pointer would be zapped after this function call.
810
   */
811
0
  if (!has_lua_stack)
812
0
    fiber()->storage.lua.stack = NULL;
813
814
0
  return 0;
815
0
}
816
817
int
818
box_lua_call(const char *name, uint32_t name_len,
819
       struct port *args, struct port *ret)
820
0
{
821
0
  struct execute_lua_ctx ctx;
822
0
  ctx.name = name;
823
0
  ctx.name_len = name_len;
824
0
  ctx.args = args;
825
0
  ctx.takes_raw_args = false;
826
0
  return box_process_lua(HANDLER_CALL, &ctx, ret);
827
0
}
828
829
int
830
box_lua_eval(const char *expr, uint32_t expr_len,
831
       struct port *args, struct port *ret)
832
0
{
833
0
  struct execute_lua_ctx ctx;
834
0
  ctx.name = expr;
835
0
  ctx.name_len = expr_len;
836
0
  ctx.args = args;
837
0
  ctx.takes_raw_args = false;
838
0
  return box_process_lua(HANDLER_EVAL, &ctx, ret);
839
0
}
840
841
struct func_lua {
842
  /** Function object base class. */
843
  struct func base;
844
  /**
845
   * For a persistent function: a reference to the
846
   * function body. Otherwise LUA_REFNIL.
847
   */
848
  int lua_ref;
849
};
850
851
static struct func_vtab func_lua_vtab;
852
static struct func_vtab func_persistent_lua_vtab;
853
854
static const char *default_sandbox_exports[] = {
855
  "assert", "error", "ipairs", "math", "next", "pairs", "pcall", "print",
856
  "select", "string", "table", "tonumber", "tostring", "type", "unpack",
857
  "xpcall", "utf8",
858
};
859
860
/**
861
 * Assemble a new sandbox with given exports table on the top of
862
 * a given Lua stack. All modules in exports list are copied
863
 * deeply to ensure the immutability of this system object.
864
 */
865
static int
866
prepare_lua_sandbox(struct lua_State *L, const char *exports[],
867
        int export_count)
868
0
{
869
0
  lua_createtable(L, export_count, 0);
870
0
  if (export_count == 0)
871
0
    return 0;
872
0
  int rc = -1;
873
0
  const char *deepcopy = "table.deepcopy";
874
0
  int luaL_deepcopy_func_ref = LUA_REFNIL;
875
0
  int ret = box_lua_find(L, deepcopy, deepcopy + strlen(deepcopy));
876
0
  if (ret < 0)
877
0
    goto end;
878
0
  luaL_deepcopy_func_ref = luaL_ref(L, LUA_REGISTRYINDEX);
879
0
  assert(luaL_deepcopy_func_ref != LUA_REFNIL);
880
0
  for (int i = 0; i < export_count; i++) {
881
0
    uint32_t name_len = strlen(exports[i]);
882
0
    ret = box_lua_find(L, exports[i], exports[i] + name_len);
883
0
    if (ret < 0)
884
0
      goto end;
885
0
    switch (lua_type(L, -1)) {
886
0
    case LUA_TTABLE:
887
0
      lua_rawgeti(L, LUA_REGISTRYINDEX,
888
0
            luaL_deepcopy_func_ref);
889
0
      lua_insert(L, -2);
890
0
      lua_call(L, 1, 1);
891
0
      break;
892
0
    case LUA_TFUNCTION:
893
0
      break;
894
0
    default:
895
0
      unreachable();
896
0
    }
897
0
    lua_setfield(L, -2, exports[i]);
898
0
  }
899
0
  rc = 0;
900
0
end:
901
0
  luaL_unref(tarantool_L, LUA_REGISTRYINDEX, luaL_deepcopy_func_ref);
902
0
  return rc;
903
0
}
904
905
/**
906
 * Assemble a Lua function object by user-defined function body.
907
 * On success, returns a Lua reference to the loaded function.
908
 * On error, returns LUA_NOREF and sets diag.
909
 */
910
static int
911
func_persistent_lua_load(const struct func_def *def)
912
0
{
913
0
  assert(def->body != NULL);
914
0
  int func_ref = LUA_NOREF;
915
0
  int top = lua_gettop(tarantool_L);
916
0
  struct region *region = &fiber()->gc;
917
0
  size_t region_svp = region_used(region);
918
0
  const char *load_pref = "return ";
919
0
  uint32_t load_str_sz =
920
0
    strlen(load_pref) + strlen(def->body) + 1;
921
0
  char *load_str = region_alloc(region, load_str_sz);
922
0
  if (load_str == NULL) {
923
0
    diag_set(OutOfMemory, load_str_sz, "region", "load_str");
924
0
    return LUA_NOREF;
925
0
  }
926
0
  snprintf(load_str, load_str_sz, "%s%s", load_pref, def->body);
927
928
  /*
929
   * Perform loading of the persistent Lua function
930
   * in a new sandboxed Lua thread. The sandbox is
931
   * required to guarantee the safety of executing
932
   * an arbitrary user-defined code
933
   * (e.g. body = 'fiber.yield()').
934
   */
935
0
  lua_State *coro_L = luaT_newthread(tarantool_L);
936
0
  if (coro_L == NULL)
937
0
    return LUA_NOREF;
938
0
  if (!def->is_sandboxed) {
939
    /*
940
     * Keep the original env to apply to a non-sandboxed
941
     * persistent function. It is necessary since
942
     * the created object inherits its parent env.
943
     */
944
0
    lua_getfenv(tarantool_L, -1);
945
0
    lua_insert(tarantool_L, -2);
946
0
  }
947
0
  if (prepare_lua_sandbox(tarantool_L, NULL, 0) != 0)
948
0
    unreachable();
949
0
  lua_setfenv(tarantool_L, -2);
950
0
  int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
951
0
  if (luaL_loadstring(coro_L, load_str) != 0 ||
952
0
      lua_pcall(coro_L, 0, 1, 0) != 0) {
953
0
    diag_set(ClientError, ER_LOAD_FUNCTION, def->name,
954
0
       luaT_tolstring(coro_L, -1, NULL));
955
0
    goto end;
956
0
  }
957
0
  if (!lua_isfunction(coro_L, -1)) {
958
0
    diag_set(ClientError, ER_LOAD_FUNCTION, def->name,
959
0
       "given body doesn't define a function");
960
0
    goto end;
961
0
  }
962
0
  lua_xmove(coro_L, tarantool_L, 1);
963
0
  if (def->is_sandboxed) {
964
0
    if (prepare_lua_sandbox(tarantool_L, default_sandbox_exports,
965
0
          nelem(default_sandbox_exports)) != 0) {
966
0
      diag_add(ClientError, ER_LOAD_FUNCTION,
967
0
         def->name, "can't prepare a Lua sandbox");
968
0
      goto end;
969
0
    }
970
0
  } else {
971
0
    lua_insert(tarantool_L, -2);
972
0
  }
973
0
  lua_setfenv(tarantool_L, -2);
974
0
  func_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
975
0
end:
976
0
  lua_settop(tarantool_L, top);
977
0
  region_truncate(region, region_svp);
978
0
  luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
979
0
  return func_ref;
980
0
}
981
982
struct func *
983
func_lua_new(const struct func_def *def)
984
0
{
985
0
  assert(def->language == FUNC_LANGUAGE_LUA);
986
0
  struct func_lua *func =
987
0
    (struct func_lua *) malloc(sizeof(struct func_lua));
988
0
  if (func == NULL) {
989
0
    diag_set(OutOfMemory, sizeof(*func), "malloc", "func");
990
0
    return NULL;
991
0
  }
992
0
  if (def->body != NULL) {
993
0
    func->lua_ref = func_persistent_lua_load(def);
994
0
    if (func->lua_ref == LUA_NOREF) {
995
0
      free(func);
996
0
      return NULL;
997
0
    }
998
0
    func->base.vtab = &func_persistent_lua_vtab;
999
0
  } else {
1000
0
    func->lua_ref = LUA_REFNIL;
1001
0
    func->base.vtab = &func_lua_vtab;
1002
0
  }
1003
0
  return &func->base;
1004
0
}
1005
1006
static void
1007
func_lua_destroy(struct func *func)
1008
0
{
1009
0
  assert(func != NULL && func->def->language == FUNC_LANGUAGE_LUA);
1010
0
  assert(func->vtab == &func_lua_vtab);
1011
0
  TRASH(func);
1012
0
  free(func);
1013
0
}
1014
1015
static inline int
1016
func_lua_call(struct func *func, struct port *args, struct port *ret)
1017
0
{
1018
0
  assert(func != NULL && func->def->language == FUNC_LANGUAGE_LUA);
1019
0
  assert(func->vtab == &func_lua_vtab);
1020
0
  struct execute_lua_ctx ctx;
1021
0
  ctx.name = func->def->name;
1022
0
  ctx.name_len = func->def->name_len;
1023
0
  ctx.args = args;
1024
0
  ctx.takes_raw_args = func->def->opts.takes_raw_args;
1025
0
  return box_process_lua(HANDLER_CALL, &ctx, ret);
1026
0
}
1027
1028
static struct func_vtab func_lua_vtab = {
1029
  .call = func_lua_call,
1030
  .destroy = func_lua_destroy,
1031
};
1032
1033
static void
1034
func_persistent_lua_unload(struct func_lua *func)
1035
0
{
1036
0
  luaL_unref(tarantool_L, LUA_REGISTRYINDEX, func->lua_ref);
1037
0
}
1038
1039
static void
1040
func_persistent_lua_destroy(struct func *base)
1041
0
{
1042
0
  assert(base != NULL && base->def->language == FUNC_LANGUAGE_LUA &&
1043
0
         base->def->body != NULL);
1044
0
  assert(base->vtab == &func_persistent_lua_vtab);
1045
0
  struct func_lua *func = (struct func_lua *) base;
1046
0
  func_persistent_lua_unload(func);
1047
0
  free(func);
1048
0
}
1049
1050
static inline int
1051
func_persistent_lua_call(struct func *base, struct port *args, struct port *ret)
1052
0
{
1053
0
  assert(base != NULL && base->def->language == FUNC_LANGUAGE_LUA &&
1054
0
         base->def->body != NULL);
1055
0
  assert(base->vtab == &func_persistent_lua_vtab);
1056
0
  struct func_lua *func = (struct func_lua *)base;
1057
0
  struct execute_lua_ctx ctx;
1058
0
  ctx.lua_ref = func->lua_ref;
1059
0
  ctx.args = args;
1060
0
  ctx.takes_raw_args = base->def->opts.takes_raw_args;
1061
0
  return box_process_lua(HANDLER_CALL_BY_REF, &ctx, ret);
1062
1063
0
}
1064
1065
static struct func_vtab func_persistent_lua_vtab = {
1066
  .call = func_persistent_lua_call,
1067
  .destroy = func_persistent_lua_destroy,
1068
};
1069
1070
static int
1071
lbox_module_reload(lua_State *L)
1072
0
{
1073
0
  if (box_check_configured() != 0)
1074
0
    return luaT_error(L);
1075
0
  const char *name = luaT_checkstring(L, 1);
1076
0
  if (box_module_reload(name) != 0)
1077
0
    return luaT_error(L);
1078
0
  return 0;
1079
0
}
1080
1081
int
1082
lbox_func_call(struct lua_State *L)
1083
0
{
1084
0
  if (box_check_configured() != 0)
1085
0
    return luaT_error(L);
1086
0
  if (lua_gettop(L) < 1 || !lua_isstring(L, 1)) {
1087
0
    diag_set(IllegalParams, "Use func:call(...)");
1088
0
    return luaT_error(L);
1089
0
  }
1090
1091
0
  size_t name_len;
1092
0
  const char *name = lua_tolstring(L, 1, &name_len);
1093
0
  struct func *func = func_by_name(name, name_len);
1094
0
  if (func == NULL) {
1095
0
    diag_set(ClientError, ER_NO_SUCH_FUNCTION,
1096
0
       tt_cstr(name, name_len));
1097
0
    return luaT_error(L);
1098
0
  }
1099
1100
  /*
1101
   * Prepare a new Lua stack for input arguments
1102
   * before the function call to pass it into the
1103
   * pcall-sandboxed tarantool_L handler.
1104
   */
1105
0
  lua_State *args_L = luaT_newthread(tarantool_L);
1106
0
  if (args_L == NULL)
1107
0
    return luaT_error(L);
1108
0
  int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
1109
0
  lua_xmove(L, args_L, lua_gettop(L) - 1);
1110
0
  struct port args;
1111
0
  port_lua_create(&args, args_L);
1112
0
  ((struct port_lua *) &args)->ref = coro_ref;
1113
1114
0
  struct port ret;
1115
0
  if (func_call(func, &args, &ret) != 0) {
1116
0
    port_destroy(&args);
1117
0
    return luaT_error(L);
1118
0
  }
1119
1120
0
  int top = lua_gettop(L);
1121
0
  port_dump_lua(&ret, L, PORT_DUMP_LUA_MODE_FLAT);
1122
0
  int cnt = lua_gettop(L) - top;
1123
1124
0
  port_destroy(&ret);
1125
0
  port_destroy(&args);
1126
0
  return cnt;
1127
0
}
1128
1129
static void
1130
lbox_func_new(struct lua_State *L, struct func *func)
1131
0
{
1132
0
  lua_getfield(L, LUA_GLOBALSINDEX, "box");
1133
0
  lua_getfield(L, -1, "func");
1134
0
  if (!lua_istable(L, -1)) {
1135
0
    lua_pop(L, 1); /* pop nil */
1136
0
    lua_newtable(L);
1137
0
    lua_setfield(L, -2, "func");
1138
0
    lua_getfield(L, -1, "func");
1139
0
  }
1140
0
  lua_rawgeti(L, -1, func->def->fid);
1141
0
  if (lua_isnil(L, -1)) {
1142
    /*
1143
     * If the function already exists, modify it,
1144
     * rather than create a new one -- to not
1145
     * invalidate Lua variable references to old func
1146
     * outside the box.schema.func[].
1147
     */
1148
0
    lua_pop(L, 1);
1149
0
    lua_newtable(L);
1150
0
    lua_rawseti(L, -2, func->def->fid);
1151
0
    lua_rawgeti(L, -1, func->def->fid);
1152
0
  } else {
1153
    /* Clear the reference to old func by old name. */
1154
0
    lua_getfield(L, -1, "name");
1155
0
    lua_pushnil(L);
1156
0
    lua_settable(L, -4);
1157
0
  }
1158
0
  int top = lua_gettop(L);
1159
0
  lua_pushstring(L, "id");
1160
0
  lua_pushnumber(L, func->def->fid);
1161
0
  lua_settable(L, top);
1162
0
  lua_pushstring(L, "name");
1163
0
  lua_pushstring(L, func->def->name);
1164
0
  lua_settable(L, top);
1165
0
  lua_pushstring(L, "setuid");
1166
0
  lua_pushboolean(L, func->def->setuid);
1167
0
  lua_settable(L, top);
1168
0
  lua_pushstring(L, "language");
1169
0
  lua_pushstring(L, func_language_strs[func->def->language]);
1170
0
  lua_settable(L, top);
1171
0
  lua_pushstring(L, "returns");
1172
0
  lua_pushstring(L, field_type_strs[func->def->returns]);
1173
0
  lua_settable(L, top);
1174
0
  lua_pushstring(L, "aggregate");
1175
0
  lua_pushstring(L, func_aggregate_strs[func->def->aggregate]);
1176
0
  lua_settable(L, top);
1177
0
  lua_pushstring(L, "body");
1178
0
  if (func->def->body != NULL)
1179
0
    lua_pushstring(L, func->def->body);
1180
0
  else
1181
0
    lua_pushnil(L);
1182
0
  lua_settable(L, top);
1183
0
  lua_pushstring(L, "comment");
1184
0
  if (func->def->comment != NULL)
1185
0
    lua_pushstring(L, func->def->comment);
1186
0
  else
1187
0
    lua_pushnil(L);
1188
0
  lua_settable(L, top);
1189
0
  lua_pushstring(L, "exports");
1190
0
  lua_newtable(L);
1191
0
  lua_pushboolean(L, func->def->exports.lua);
1192
0
  lua_setfield(L, -2, "lua");
1193
0
  lua_pushboolean(L, func->def->exports.sql);
1194
0
  lua_setfield(L, -2, "sql");
1195
0
  lua_settable(L, -3);
1196
0
  lua_pushstring(L, "is_deterministic");
1197
0
  lua_pushboolean(L, func->def->is_deterministic);
1198
0
  lua_settable(L, top);
1199
0
  lua_pushstring(L, "is_multikey");
1200
0
  lua_pushboolean(L, func->def->opts.is_multikey);
1201
0
  lua_settable(L, top);
1202
0
  lua_pushstring(L, "takes_raw_args");
1203
0
  lua_pushboolean(L, func->def->opts.takes_raw_args);
1204
0
  lua_settable(L, top);
1205
0
  lua_pushstring(L, "is_sandboxed");
1206
0
  if (func->def->body != NULL)
1207
0
    lua_pushboolean(L, func->def->is_sandboxed);
1208
0
  else
1209
0
    lua_pushnil(L);
1210
0
  lua_settable(L, top);
1211
1212
  /* Bless func object. */
1213
0
  lua_getfield(L, LUA_GLOBALSINDEX, "box");
1214
0
  lua_pushstring(L, "schema");
1215
0
  lua_gettable(L, -2);
1216
0
  lua_pushstring(L, "func");
1217
0
  lua_gettable(L, -2);
1218
0
  lua_pushstring(L, "bless");
1219
0
  lua_gettable(L, -2);
1220
1221
0
  lua_pushvalue(L, top);
1222
0
  lua_call(L, 1, 0);
1223
0
  lua_pop(L, 3);
1224
1225
0
  lua_setfield(L, -2, func->def->name);
1226
1227
0
  lua_pop(L, 2);
1228
0
}
1229
1230
static void
1231
lbox_func_delete(struct lua_State *L, struct func *func)
1232
0
{
1233
0
  uint32_t fid = func->def->fid;
1234
0
  lua_getfield(L, LUA_GLOBALSINDEX, "box");
1235
0
  lua_getfield(L, -1, "func");
1236
0
  assert(!lua_isnil(L, -1));
1237
0
  lua_rawgeti(L, -1, fid);
1238
0
  if (!lua_isnil(L, -1)) {
1239
0
    lua_getfield(L, -1, "name");
1240
0
    lua_pushnil(L);
1241
0
    lua_rawset(L, -4);
1242
0
    lua_pop(L, 1); /* pop func */
1243
0
    lua_pushnil(L);
1244
0
    lua_rawseti(L, -2, fid);
1245
0
  } else {
1246
0
    lua_pop(L, 1);
1247
0
  }
1248
0
  lua_pop(L, 2); /* box, func */
1249
0
}
1250
1251
static int
1252
lbox_func_new_or_delete(struct trigger *trigger, void *event)
1253
0
{
1254
0
  struct lua_State *L = (struct lua_State *) trigger->data;
1255
0
  struct func *func = (struct func *)event;
1256
0
  if (!func->def->exports.lua)
1257
0
    return 0;
1258
0
  if (func_by_id(func->def->fid) != NULL)
1259
0
    lbox_func_new(L, func);
1260
0
  else
1261
0
    lbox_func_delete(L, func);
1262
0
  return 0;
1263
0
}
1264
1265
static int
1266
lbox_box_lua_call_runtime_priv_reset(struct lua_State *L)
1267
0
{
1268
0
  if (lua_gettop(L) != 0) {
1269
0
    diag_set(IllegalParams,
1270
0
       "Usage: box.internal.lua_call_runtime_priv_reset()");
1271
0
    return luaT_error(L);
1272
0
  }
1273
1274
0
  box_lua_call_runtime_priv_reset();
1275
0
  return 0;
1276
0
}
1277
1278
static int
1279
lbox_box_lua_call_runtime_priv_grant(struct lua_State *L)
1280
0
{
1281
0
  if (lua_gettop(L) != 2 || lua_type(L, 1) != LUA_TSTRING ||
1282
0
      lua_type(L, 2) != LUA_TSTRING) {
1283
0
    diag_set(IllegalParams,
1284
0
       "Usage: box.internal.lua_call_runtime_priv_grant(user, func)");
1285
0
    return luaT_error(L);
1286
0
  }
1287
1288
0
  size_t grantee_name_len;
1289
0
  const char *grantee_name = luaL_checklstring(L, 1, &grantee_name_len);
1290
1291
0
  size_t func_name_len;
1292
0
  const char *func_name = luaL_checklstring(L, 2, &func_name_len);
1293
1294
0
  box_lua_call_runtime_priv_grant(grantee_name,
1295
0
          (uint32_t)grantee_name_len,
1296
0
          func_name, (uint32_t)func_name_len);
1297
0
  return 0;
1298
0
}
1299
1300
static void
1301
call_serializer_update_options(void)
1302
0
{
1303
0
  luaL_serializer_copy_options(&call_serializer_no_error_ext,
1304
0
             luaL_msgpack_default);
1305
0
  call_serializer_no_error_ext.encode_error_as_ext = 0;
1306
0
}
1307
1308
static int
1309
on_msgpack_serializer_update(struct trigger *trigger, void *event)
1310
0
{
1311
0
  (void)trigger;
1312
0
  (void)event;
1313
0
  call_serializer_update_options();
1314
0
  return 0;
1315
0
}
1316
1317
static TRIGGER(on_alter_func_in_lua, lbox_func_new_or_delete);
1318
1319
static const struct luaL_Reg boxlib_internal[] = {
1320
  {"call_loadproc",  lbox_call_loadproc},
1321
  {"module_reload", lbox_module_reload},
1322
  {"func_call", lbox_func_call},
1323
  {"lua_call_runtime_priv_grant", lbox_box_lua_call_runtime_priv_grant},
1324
  {"lua_call_runtime_priv_reset", lbox_box_lua_call_runtime_priv_reset},
1325
  {NULL, NULL}
1326
};
1327
1328
void
1329
box_lua_call_init(struct lua_State *L)
1330
0
{
1331
0
  call_serializer_update_options();
1332
0
  trigger_create(&call_serializer_no_error_ext.update_trigger,
1333
0
           on_msgpack_serializer_update, NULL, NULL);
1334
0
  trigger_add(&luaL_msgpack_default->on_update,
1335
0
        &call_serializer_no_error_ext.update_trigger);
1336
1337
0
  luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal", 0);
1338
0
  luaL_setfuncs(L, boxlib_internal, 0);
1339
0
  lua_pop(L, 1);
1340
  /*
1341
   * Register the trigger that will push persistent
1342
   * Lua functions objects to Lua.
1343
   */
1344
0
  on_alter_func_in_lua.data = L;
1345
0
  trigger_add(&on_alter_func, &on_alter_func_in_lua);
1346
1347
0
  lua_CFunction handles[] = {
1348
0
    [HANDLER_CALL] = execute_lua_call,
1349
0
    [HANDLER_CALL_BY_REF] = execute_lua_call_by_ref,
1350
0
    [HANDLER_ENCODE_CALL] = encode_lua_call,
1351
0
    [HANDLER_ENCODE_CALL_16] = encode_lua_call_16,
1352
0
    [HANDLER_EVAL] = execute_lua_eval,
1353
0
  };
1354
1355
0
  for (int i = 0; i < HANDLER_MAX; i++) {
1356
0
    lua_pushcfunction(L, handles[i]);
1357
0
    execute_lua_refs[i] = luaL_ref(L, LUA_REGISTRYINDEX);
1358
0
  }
1359
1360
#if 0
1361
  /* Get CTypeID for `struct port *' */
1362
  int rc = luaL_cdef(L, "struct port;");
1363
  assert(rc == 0);
1364
  (void) rc;
1365
  CTID_STRUCT_PORT_PTR = luaL_ctypeid(L, "struct port *");
1366
  assert(CTID_STRUCT_TUPLE_REF != 0);
1367
#endif
1368
0
}