Line data Source code
1 :
2 : /*
3 : * Copyright (C) Xiaozhe Wang (chaoslawful)
4 : * Copyright (C) Yichun Zhang (agentzh)
5 : */
6 :
7 :
8 : #ifndef DDEBUG
9 : #define DDEBUG 0
10 : #endif
11 : #include "ddebug.h"
12 :
13 :
14 : #include <nginx.h>
15 : #include "ngx_http_lua_clfactory.h"
16 :
17 :
18 : #define CLFACTORY_BEGIN_CODE "return function() "
19 : #define CLFACTORY_BEGIN_SIZE (sizeof(CLFACTORY_BEGIN_CODE) - 1)
20 :
21 : #define CLFACTORY_END_CODE "\nend"
22 : #define CLFACTORY_END_SIZE (sizeof(CLFACTORY_END_CODE) - 1)
23 :
24 :
25 : /*
26 : * taken from chaoslawful:
27 : * Lua bytecode header Luajit bytecode header
28 : * -------------- --------------
29 : * | \033Lua | 0-3 | \033LJ | 0-2
30 : * -------------- --------------
31 : * | LuaC | 4 | bytecode | 3
32 : * | Version | | version |
33 : * -------------- --------------
34 : * | LuaC | 5 | misc flag | 4 [F|S|B]
35 : * | Format | --------------
36 : * -------------- | chunkname | ULEB128 var-len
37 : * | Endian | 6 | len | encoded uint32
38 : * -------------- --------------
39 : * | size of | 7 | chunkname |
40 : * | int | | str no \0 |
41 : * -------------- --------------
42 : * | size of | 8
43 : * | size_t |
44 : * --------------
45 : * | size of | 9
46 : * | instruction|
47 : * --------------
48 : * | size of | 10
49 : * | number |
50 : * --------------
51 : * | number | 11
52 : * | is int? |
53 : * --------------
54 : */
55 :
56 :
57 : /*
58 : * CLOSURE 0 0 RETURN 0 2 RETURN 0 1
59 : * length(Instruction) = 4 or 8
60 : * little endian or big endian
61 : */
62 : #define LUA_LITTLE_ENDIAN_4BYTES_CODE \
63 : "\x24\x00\x00\x00\x1e\x00\x00\x01\x1e\x00\x80\x00"
64 : #define LUA_LITTLE_ENDIAN_8BYTES_CODE \
65 : "\x24\x00\x00\x00\x00\x00\x00\x00\x1e\x00\x00\x01" \
66 : "\x00\x00\x00\x00\x1e\x00\x80\x00\x00\x00\x00\x00"
67 : #define LUA_BIG_ENDIAN_4BYTES_CODE \
68 : "\x00\x00\x00\x24\x01\x00\x00\x1e\x00\x08\x00\x1e"
69 : #define LUA_BIG_ENDIAN_8BYTES_CODE \
70 : "\x00\x00\x00\x00\x00\x00\x00\x24\x00\x00\x00\x00" \
71 : "\x01\x00\x00\x1e\x00\x00\x00\x00\x00\x08\x00\x1e"
72 : #define LUA_LITTLE_ENDIAN_4BYTES_CODE_LEN (4 + 4 + 4)
73 : #define LUA_LITTLE_ENDIAN_8BYTES_CODE_LEN (8 + 8 + 8)
74 : #define LUA_BIG_ENDIAN_4BYTES_CODE_LEN (4 + 4 + 4)
75 : #define LUA_BIG_ENDIAN_8BYTES_CODE_LEN (8 + 8 + 8)
76 : #define LUAC_HEADERSIZE 12
77 : #define LUAC_VERSION 0x51
78 :
79 :
80 : /*
81 : * taken from chaoslawful:
82 : * Lua Proto
83 : * ---------------------
84 : * | String | Can be empty string
85 : * | [source] | (stripped or internal function)
86 : * ---------------------
87 : * | Int | At which line this function is defined
88 : * | [linedefined] |
89 : * ---------------------
90 : * | Int | At while line this function definition ended
91 : * | [lastlinedefined] |
92 : * ---------------------
93 : * | Char | Number of upvalues referenced by this function
94 : * | [nups] |
95 : * ---------------------
96 : * | Char | Number of parameters of this function
97 : * | [numparams] |
98 : * ---------------------
99 : * | Char | Does this function has variable number of arguments?
100 : * | [is_var_arg] | main function always set to VARARG_ISVARARG (2)
101 : * ---------------------
102 : * | Char | Maximum stack size this function used
103 : * | [maxstacksize] | Initially set to 2
104 : * ---------------------
105 : * | Vector(instr) | Code instructions of this function
106 : * | [code] |
107 : * ---------------------
108 : * | Int | Number of constants referenced by this function
109 : * | [sizek] |
110 : * ---------------------
111 : * | Char | ------------------------------------
112 : * | type of [k[i]] | The type and content of constants |
113 : * --------------------- |-> repeat for i in
114 : * | Char if boolean | No content part if type is NIL | [1..sizek]
115 : * | Number if number | ------------------------------------
116 : * | String if string |
117 : * ---------------------
118 : * | Int | Number of internal functions
119 : * | [sizep] |
120 : * ---------------------
121 : * | Function | -> repeat for i in [1..sizep]
122 : * | at [p[i]] |
123 : * ---------------------
124 : * | Vector | Debug lineinfo vector
125 : * | [lineinfo] | Empty vector here if dubug info is stripped
126 : * ---------------------
127 : * | Int | Number of local variable in this function
128 : * | [sizelocvars] | 0 if debug info is stripped
129 : * ---------------------
130 : * | String | ------------------------------------
131 : * | [locvars[i]] | Name of local var i |
132 : * | .varname] | |
133 : * --------------------- |
134 : * | Int | instruction counter |
135 : * | [locvars[i]] | where lcoal var i start to be |-> repeat for i in
136 : * | .startpc] | referenced | [0..sizelocvars]
137 : * --------------------- |
138 : * | Int | instruction counter, where local |
139 : * | [locvars[i]] | var i ceased to be referenced |
140 : * | .endpc] | ------------------------------------
141 : * ---------------------
142 : * | Int | Number of upvalues referenced by this function,
143 : * | [sizeupvalues] | 0 if stripped
144 : * ---------------------
145 : * | String | -> repeat for i in[0..sizeupvalues]
146 : * | [upvalues[i]] |
147 : * ---------------------
148 : */
149 :
150 : #define POS_SOURCE_STR_LEN LUAC_HEADERSIZE
151 : #define POS_START_LINE (POS_SOURCE_STR_LEN + sizeof(size_t))
152 : #define POS_LAST_LINE (POS_START_LINE + sizeof(int))
153 : #define POS_NUM_OF_UPVS (POS_LAST_LINE + sizeof(int))
154 : #define POS_NUM_OF_PARA (POS_NUM_OF_UPVS + sizeof(char))
155 : #define POS_IS_VAR_ARG (POS_NUM_OF_PARA + sizeof(char))
156 : #define POS_MAX_STACK_SIZE (POS_IS_VAR_ARG + sizeof(char))
157 : #define POS_NUM_OF_INST (POS_MAX_STACK_SIZE +sizeof(char))
158 : #define POS_BYTECODE (POS_NUM_OF_INST + sizeof(int))
159 : #define MAX_BEGIN_CODE_SIZE \
160 : (POS_BYTECODE + LUA_LITTLE_ENDIAN_8BYTES_CODE_LEN \
161 : + sizeof(int) + sizeof(int))
162 : #define MAX_END_CODE_SIZE (sizeof(int) + sizeof(int) + sizeof(int))
163 :
164 : /*
165 : * taken from chaoslawful:
166 : * Luajit bytecode format
167 : * ---------------------
168 : * | HEAD | Luajit bytecode head
169 : * ---------------------
170 : * | Internal | All internal functions
171 : * | functions |
172 : * ---------------------
173 : * | ULEB128 | Rest data total length of this function
174 : * | [Date len of | (not include itself)
175 : * | this function] |
176 : * ---------------------
177 : * | Char | F(ffi) | V(vararg)| C(has internal funcs)
178 : * | [func flag] |
179 : * ---------------------
180 : * | Char | Number of parameters of this function
181 : * | [numparams] |
182 : * ---------------------
183 : * | Char |
184 : * | [framesize] |
185 : * ---------------------
186 : * | Char | Number of upvalues referenced by this function
187 : * | [sizeupvalues] |
188 : * ---------------------
189 : * | ULEB128 | Number of collectable constants referenced
190 : * | [sizekgc] | by this function
191 : * ---------------------
192 : * | ULEB128 | Number of lua number constants referenced
193 : * | [sizekn] | by this function
194 : * ---------------------
195 : * | ULEB128 | Number of bytecode instructions of this function
196 : * | [sizebc]m1 | minus 1 to omit the BC_FUNCV/BC_FUNCF header bytecode
197 : * ---------------------
198 : * | ULEB128 |
199 : * | [size of dbg | Size of debug lineinfo map, available when not stripped
200 : * | lineinfo] |
201 : * ---------------------
202 : * | ULEB128 | Available when not stripped
203 : * | [firstline] | The first line of this function's definition
204 : * ---------------------
205 : * | ULEB128 | Available when not stripped
206 : * | [numline] | The number of lines of this function's definition
207 : * ---------------------
208 : * | [bytecode] | Bytecode instructions of this function
209 : * ---------------------
210 : * |[upvalue ref slots]| [sizeupvalues] * 2
211 : * ---------------------
212 : * | [collectable | [sizekgc] elems, variable length
213 : * | constants] |
214 : * ---------------------
215 : * | [lua number | [sizekn] elems, variable length
216 : * | constants] |
217 : * ---------------------
218 : * | [debug lineinfo | Length is the calculated size of debug lineinfo above
219 : * | | Only available if not stripped
220 : * ---------------------
221 : * | Char |
222 : * | [\x00] | Footer
223 : * ---------------------
224 : */
225 :
226 : /* bytecode for luajit 2.0 */
227 :
228 : #define LJ20_LITTLE_ENDIAN_CODE_STRIPPED \
229 : "\x14\x03\x00\x01\x00\x01\x00\x03" \
230 : "\x31\x00\x00\x00\x30\x00\x00\x80\x48\x00\x02\x00" \
231 : "\x00\x00"
232 :
233 : #define LJ20_BIG_ENDIAN_CODE_STRIPPED \
234 : "\x14\x03\x00\x01\x00\x01\x00\x03" \
235 : "\x00\x00\x00\x31\x80\x00\x00\x30\x00\x02\x00\x48" \
236 : "\x00\x00"
237 :
238 : #define LJ20_LITTLE_ENDIAN_CODE \
239 : "\x15\x03\x00\x01\x00\x01\x00\x03\x00" \
240 : "\x31\x00\x00\x00\x30\x00\x00\x80\x48\x00\x02\x00" \
241 : "\x00\x00"
242 :
243 : #define LJ20_BIG_ENDIAN_CODE \
244 : "\x15\x03\x00\x01\x00\x01\x00\x03\x00" \
245 : "\x00\x00\x00\x31\x80\x00\x00\x30\x00\x02\x00\x48" \
246 : "\x00\x00"
247 :
248 : /* bytecode for luajit 2.1 */
249 :
250 : #define LJ21_LITTLE_ENDIAN_CODE_STRIPPED \
251 : "\x14\x03\x00\x01\x00\x01\x00\x03" \
252 : "\x33\x00\x00\x00\x32\x00\x00\x80\x4c\x00\x02\x00" \
253 : "\x00\x00"
254 :
255 : #define LJ21_BIG_ENDIAN_CODE_STRIPPED \
256 : "\x14\x03\x00\x01\x00\x01\x00\x03" \
257 : "\x00\x00\x00\x33\x80\x00\x00\x32\x00\x02\x00\x4c" \
258 : "\x00\x00"
259 :
260 : #define LJ21_LITTLE_ENDIAN_CODE \
261 : "\x15\x03\x00\x01\x00\x01\x00\x03\x00" \
262 : "\x33\x00\x00\x00\x32\x00\x00\x80\x4c\x00\x02\x00" \
263 : "\x00\x00"
264 :
265 : #define LJ21_BIG_ENDIAN_CODE \
266 : "\x15\x03\x00\x01\x00\x01\x00\x03\x00" \
267 : "\x00\x00\x00\x33\x80\x00\x00\x32\x00\x02\x00\x4c" \
268 : "\x00\x00"
269 :
270 : #define LJ_CODE_LEN 23
271 : #define LJ_CODE_LEN_STRIPPED 22
272 : #define LJ_HEADERSIZE 5
273 : #define LJ_BCDUMP_F_BE 0x01
274 : #define LJ_BCDUMP_F_STRIP 0x02
275 : #define LJ21_BCDUMP_VERSION 2
276 : #define LJ20_BCDUMP_VERSION 1
277 : #define LJ_SIGNATURE "\x1b\x4c\x4a"
278 :
279 :
280 : typedef enum {
281 : NGX_LUA_TEXT_FILE,
282 : NGX_LUA_BT_LUA,
283 : NGX_LUA_BT_LJ
284 : } ngx_http_lua_clfactory_file_type_e;
285 :
286 :
287 : enum {
288 : NGX_LUA_READER_BUFSIZE = 4096
289 : };
290 :
291 :
292 : typedef struct {
293 : ngx_http_lua_clfactory_file_type_e file_type;
294 :
295 : int sent_begin;
296 : int sent_end;
297 : int extraline;
298 : FILE *f;
299 : size_t begin_code_len;
300 : size_t end_code_len;
301 : size_t rest_len;
302 : union {
303 : char *ptr;
304 : char str[MAX_BEGIN_CODE_SIZE];
305 : } begin_code;
306 : union {
307 : char *ptr;
308 : char str[MAX_END_CODE_SIZE];
309 : } end_code;
310 : char buff[NGX_LUA_READER_BUFSIZE];
311 : } ngx_http_lua_clfactory_file_ctx_t;
312 :
313 :
314 : typedef struct {
315 : int sent_begin;
316 : int sent_end;
317 : const char *s;
318 : size_t size;
319 : } ngx_http_lua_clfactory_buffer_ctx_t;
320 :
321 :
322 : static const char *ngx_http_lua_clfactory_getF(lua_State *L, void *ud,
323 : size_t *size);
324 : static int ngx_http_lua_clfactory_errfile(lua_State *L, const char *what,
325 : int fname_index);
326 : static const char *ngx_http_lua_clfactory_getS(lua_State *L, void *ud,
327 : size_t *size);
328 : static long ngx_http_lua_clfactory_file_size(FILE *f);
329 :
330 :
331 : int
332 0 : ngx_http_lua_clfactory_bytecode_prepare(lua_State *L,
333 : ngx_http_lua_clfactory_file_ctx_t *lf, int fname_index)
334 : {
335 0 : int x = 1, size_of_int, size_of_size_t, little_endian,
336 : size_of_inst, version, stripped;
337 : static int num_of_inst = 3, num_of_inter_func = 1;
338 : const char *emsg, *serr, *bytecode;
339 : size_t size, bytecode_len;
340 : long fsize;
341 :
342 0 : serr = NULL;
343 :
344 0 : *lf->begin_code.str = LUA_SIGNATURE[0];
345 :
346 0 : if (lf->file_type == NGX_LUA_BT_LJ) {
347 0 : size = fread(lf->begin_code.str + 1, 1, LJ_HEADERSIZE - 1, lf->f);
348 :
349 0 : if (size != LJ_HEADERSIZE - 1) {
350 0 : serr = strerror(errno);
351 0 : emsg = "cannot read header";
352 0 : goto error;
353 : }
354 :
355 0 : version = *(lf->begin_code.str + 3);
356 :
357 : dd("version: %d", (int) version);
358 :
359 0 : if (ngx_memcmp(lf->begin_code.str, LJ_SIGNATURE,
360 : sizeof(LJ_SIGNATURE) - 1))
361 : {
362 0 : emsg = "bad byte-code header";
363 0 : goto error;
364 : }
365 :
366 : #if defined(DDEBUG) && (DDEBUG)
367 : {
368 : dd("==LJ_BT_HEADER==");
369 : size_t i;
370 : for (i = 0; i < LJ_HEADERSIZE; i++) {
371 : dd("%ld: 0x%02X", i, (unsigned)(u_char) lf->begin_code.str[i]);
372 : }
373 : dd("==LJ_BT_HEADER_END==");
374 : }
375 : #endif
376 :
377 0 : lf->begin_code_len = LJ_HEADERSIZE;
378 0 : little_endian = !((*(lf->begin_code.str + 4)) & LJ_BCDUMP_F_BE);
379 0 : stripped = (*(lf->begin_code.str + 4)) & LJ_BCDUMP_F_STRIP;
380 :
381 : dd("stripped: %d", (int) stripped);
382 :
383 0 : if (version == LJ21_BCDUMP_VERSION) {
384 0 : if (stripped) {
385 0 : if (little_endian) {
386 0 : lf->end_code.ptr = LJ21_LITTLE_ENDIAN_CODE_STRIPPED;
387 :
388 : } else {
389 0 : lf->end_code.ptr = LJ21_BIG_ENDIAN_CODE_STRIPPED;
390 : }
391 :
392 0 : lf->end_code_len = LJ_CODE_LEN_STRIPPED;
393 :
394 : } else {
395 0 : if (little_endian) {
396 0 : lf->end_code.ptr = LJ21_LITTLE_ENDIAN_CODE;
397 :
398 : } else {
399 0 : lf->end_code.ptr = LJ21_BIG_ENDIAN_CODE;
400 : }
401 :
402 0 : lf->end_code_len = LJ_CODE_LEN;
403 : }
404 :
405 0 : } else if (version == LJ20_BCDUMP_VERSION) {
406 0 : if (stripped) {
407 0 : if (little_endian) {
408 0 : lf->end_code.ptr = LJ20_LITTLE_ENDIAN_CODE_STRIPPED;
409 :
410 : } else {
411 0 : lf->end_code.ptr = LJ20_BIG_ENDIAN_CODE_STRIPPED;
412 : }
413 :
414 0 : lf->end_code_len = LJ_CODE_LEN_STRIPPED;
415 :
416 : } else {
417 0 : if (little_endian) {
418 0 : lf->end_code.ptr = LJ20_LITTLE_ENDIAN_CODE;
419 :
420 : } else {
421 0 : lf->end_code.ptr = LJ20_BIG_ENDIAN_CODE;
422 : }
423 :
424 0 : lf->end_code_len = LJ_CODE_LEN;
425 : }
426 :
427 : } else {
428 0 : emsg = "bytecode format version unsupported";
429 0 : goto error;
430 : }
431 :
432 0 : fsize = ngx_http_lua_clfactory_file_size(lf->f);
433 0 : if (fsize < 0) {
434 0 : serr = strerror(errno);
435 0 : emsg = "cannot fseek/ftell";
436 0 : goto error;
437 : }
438 :
439 0 : lf->rest_len = fsize - LJ_HEADERSIZE;
440 :
441 : #if defined(DDEBUG) && (DDEBUG)
442 : {
443 : size_t i = 0;
444 : dd("==LJ_END_CODE: %ld rest_len: %ld==", lf->end_code_len,
445 : lf->rest_len);
446 :
447 : for (i = 0; i < lf->end_code_len; i++) {
448 : dd("%ld: 0x%02X", i, (unsigned) ((u_char) lf->end_code.ptr[i]));
449 : }
450 : dd("==LJ_END_CODE_END==");
451 : }
452 : #endif
453 :
454 : } else {
455 0 : size = fread(lf->begin_code.str + 1, 1, LUAC_HEADERSIZE - 1, lf->f);
456 :
457 0 : if (size != LUAC_HEADERSIZE - 1) {
458 0 : serr = strerror(errno);
459 0 : emsg = "cannot read header";
460 0 : goto error;
461 : }
462 :
463 0 : version = *(lf->begin_code.str + 4);
464 0 : little_endian = *(lf->begin_code.str + 6);
465 0 : size_of_int = *(lf->begin_code.str + 7);
466 0 : size_of_size_t = *(lf->begin_code.str + 8);
467 0 : size_of_inst = *(lf->begin_code.str + 9);
468 :
469 : #if defined(DDEBUG) && (DDEBUG)
470 : {
471 : dd("==LUA_BT_HEADER==");
472 : size_t i;
473 : for (i = 0; i < LUAC_HEADERSIZE; i++) {
474 : dd("%ld, 0x%02X", i, (unsigned)(u_char) lf->begin_code.str[i]);
475 : }
476 : dd("==LUA_BT_HEADER_END==");
477 : }
478 : #endif
479 :
480 0 : if (ngx_memcmp(lf->begin_code.str, LUA_SIGNATURE,
481 : sizeof(LUA_SIGNATURE) -1)
482 0 : || version != LUAC_VERSION
483 0 : || little_endian != (int) (*(char *) &x)
484 0 : || size_of_int != sizeof(int)
485 0 : || size_of_size_t != sizeof(size_t)
486 0 : || (size_of_inst != 4 && size_of_inst != 8))
487 : {
488 0 : emsg = "bad byte-code header";
489 0 : goto error;
490 : }
491 :
492 : /* clear the following fields to zero:
493 : * - source string length
494 : * - start line
495 : * - last line
496 : */
497 0 : ngx_memzero(lf->begin_code.str + POS_SOURCE_STR_LEN,
498 : sizeof(size_t) + sizeof(int) * 2);
499 : /* number of upvalues */
500 0 : *(lf->begin_code.str + POS_NUM_OF_UPVS) = 0;
501 : /* number of parameters */
502 0 : *(lf->begin_code.str + POS_NUM_OF_PARA) = 0;
503 : /* is var-argument function? */
504 0 : *(lf->begin_code.str + POS_IS_VAR_ARG) = 2;
505 : /* max stack size */
506 0 : *(lf->begin_code.str + POS_MAX_STACK_SIZE) = 2;
507 : /* number of bytecode instructions */
508 0 : ngx_memcpy(lf->begin_code.str + POS_NUM_OF_INST, &num_of_inst,
509 : sizeof(int));
510 :
511 0 : lf->begin_code_len = POS_BYTECODE;
512 :
513 0 : if (little_endian) {
514 0 : if (size_of_inst == 4) {
515 0 : bytecode = LUA_LITTLE_ENDIAN_4BYTES_CODE;
516 0 : bytecode_len = LUA_LITTLE_ENDIAN_4BYTES_CODE_LEN;
517 :
518 : } else {
519 0 : bytecode = LUA_LITTLE_ENDIAN_8BYTES_CODE;
520 0 : bytecode_len = LUA_LITTLE_ENDIAN_8BYTES_CODE_LEN;
521 : }
522 :
523 : } else {
524 0 : if (size_of_inst == 4) {
525 0 : bytecode = LUA_BIG_ENDIAN_4BYTES_CODE;
526 0 : bytecode_len = LUA_BIG_ENDIAN_4BYTES_CODE_LEN;
527 :
528 : } else {
529 0 : bytecode = LUA_BIG_ENDIAN_8BYTES_CODE;
530 0 : bytecode_len = LUA_BIG_ENDIAN_8BYTES_CODE_LEN;
531 : }
532 : }
533 :
534 : /* bytecode */
535 0 : ngx_memcpy(lf->begin_code.str + POS_BYTECODE, bytecode, bytecode_len);
536 :
537 : /* number of consts */
538 0 : ngx_memzero(lf->begin_code.str + POS_BYTECODE + bytecode_len,
539 : sizeof(int));
540 : /* number of internal functions */
541 0 : ngx_memcpy(lf->begin_code.str + POS_BYTECODE + bytecode_len
542 : + sizeof(int), &num_of_inter_func, sizeof(int));
543 :
544 0 : lf->begin_code_len += bytecode_len + sizeof(int) + sizeof(int);
545 :
546 : #if defined(DDEBUG) && (DDEBUG)
547 : {
548 : size_t i = 0;
549 : dd("==LUA_BEGIN_CODE: %ld==", lf->begin_code_len);
550 : for (i = 0; i < lf->begin_code_len; i++) {
551 : dd("%ld: 0x%02X", i, (unsigned) ((u_char) lf->begin_code.str[i]));
552 : }
553 : dd("==LUA_BEGIN_CODE_END==");
554 : }
555 : #endif
556 :
557 : /* clear the following fields to zero:
558 : * - lineinfo vector size
559 : * - number of local vars
560 : * - number of upvalues
561 : */
562 0 : ngx_memzero(lf->end_code.str, sizeof(int) * 3);
563 :
564 0 : lf->end_code_len = sizeof(int) + sizeof(int) + sizeof(int);
565 :
566 : #if defined(DDEBUG) && (DDEBUG)
567 : {
568 : size_t i = 0;
569 : dd("==LUA_END_CODE: %ld==", lf->end_code_len);
570 : for (i = 0; i < lf->end_code_len; i++) {
571 : dd("%ld: 0x%02X", i, (unsigned) ((u_char) lf->end_code.str[i]));
572 : }
573 : dd("==LUA_END_CODE_END==");
574 : }
575 : #endif
576 :
577 : }
578 :
579 0 : return 0;
580 :
581 0 : error:
582 :
583 0 : fclose(lf->f); /* close file (even in case of errors) */
584 :
585 0 : if (serr) {
586 0 : lua_pushfstring(L, "%s: %s", emsg, serr);
587 :
588 : } else {
589 0 : lua_pushstring(L, emsg);
590 : }
591 :
592 0 : lua_remove(L, fname_index);
593 :
594 0 : return LUA_ERRFILE;
595 : }
596 :
597 :
598 : ngx_int_t
599 0 : ngx_http_lua_clfactory_loadfile(lua_State *L, const char *filename)
600 : {
601 : int c, status, readstatus;
602 : ngx_flag_t sharp;
603 :
604 : ngx_http_lua_clfactory_file_ctx_t lf;
605 :
606 : /* index of filename on the stack */
607 : int fname_index;
608 :
609 0 : sharp = 0;
610 0 : fname_index = lua_gettop(L) + 1;
611 :
612 0 : lf.extraline = 0;
613 0 : lf.file_type = NGX_LUA_TEXT_FILE;
614 :
615 0 : lf.begin_code.ptr = CLFACTORY_BEGIN_CODE;
616 0 : lf.begin_code_len = CLFACTORY_BEGIN_SIZE;
617 0 : lf.end_code.ptr = CLFACTORY_END_CODE;
618 0 : lf.end_code_len = CLFACTORY_END_SIZE;
619 :
620 0 : lua_pushfstring(L, "@%s", filename);
621 :
622 0 : lf.f = fopen(filename, "r");
623 0 : if (lf.f == NULL) {
624 0 : return ngx_http_lua_clfactory_errfile(L, "open", fname_index);
625 : }
626 :
627 0 : c = getc(lf.f);
628 :
629 0 : if (c == '#') { /* Unix exec. file? */
630 0 : lf.extraline = 1;
631 :
632 0 : while ((c = getc(lf.f)) != EOF && c != '\n') {
633 : /* skip first line */
634 : }
635 :
636 0 : if (c == '\n') {
637 0 : c = getc(lf.f);
638 : }
639 :
640 0 : sharp = 1;
641 : }
642 :
643 0 : if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
644 0 : lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
645 :
646 0 : if (lf.f == NULL) {
647 0 : return ngx_http_lua_clfactory_errfile(L, "reopen", fname_index);
648 : }
649 :
650 : /* check whether lib jit exists */
651 0 : luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
652 0 : lua_getfield(L, -1, "jit"); /* get _LOADED["jit"] */
653 :
654 0 : if (lua_istable(L, -1)) {
655 0 : lf.file_type = NGX_LUA_BT_LJ;
656 :
657 : } else {
658 0 : lf.file_type = NGX_LUA_BT_LUA;
659 : }
660 :
661 0 : lua_pop(L, 2);
662 :
663 : /*
664 : * Loading bytecode with an extra header is disabled for security
665 : * reasons. This may circumvent the usual check for bytecode vs.
666 : * Lua code by looking at the first char. Since this is a potential
667 : * security violation no attempt is made to echo the chunkname either.
668 : */
669 0 : if (lf.file_type == NGX_LUA_BT_LJ && sharp) {
670 :
671 0 : if (filename) {
672 0 : fclose(lf.f); /* close file (even in case of errors) */
673 : }
674 :
675 0 : filename = lua_tostring(L, fname_index) + 1;
676 0 : lua_pushfstring(L, "bad byte-code header in %s", filename);
677 0 : lua_remove(L, fname_index);
678 :
679 0 : return LUA_ERRFILE;
680 : }
681 :
682 0 : while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {
683 : /* skip eventual `#!...' */
684 : }
685 :
686 0 : status = ngx_http_lua_clfactory_bytecode_prepare(L, &lf, fname_index);
687 :
688 0 : if (status != 0) {
689 0 : return status;
690 : }
691 :
692 0 : lf.extraline = 0;
693 : }
694 :
695 0 : if (lf.file_type == NGX_LUA_TEXT_FILE) {
696 0 : ungetc(c, lf.f);
697 : }
698 :
699 0 : lf.sent_begin = lf.sent_end = 0;
700 0 : status = lua_load(L, ngx_http_lua_clfactory_getF, &lf,
701 : lua_tostring(L, -1));
702 :
703 0 : readstatus = ferror(lf.f);
704 :
705 0 : if (filename) {
706 0 : fclose(lf.f); /* close file (even in case of errors) */
707 : }
708 :
709 0 : if (readstatus) {
710 0 : lua_settop(L, fname_index); /* ignore results from `lua_load' */
711 0 : return ngx_http_lua_clfactory_errfile(L, "read", fname_index);
712 : }
713 :
714 0 : lua_remove(L, fname_index);
715 :
716 0 : return status;
717 : }
718 :
719 :
720 : ngx_int_t
721 1 : ngx_http_lua_clfactory_loadbuffer(lua_State *L, const char *buff,
722 : size_t size, const char *name)
723 : {
724 : ngx_http_lua_clfactory_buffer_ctx_t ls;
725 :
726 1 : ls.s = buff;
727 1 : ls.size = size;
728 1 : ls.sent_begin = 0;
729 1 : ls.sent_end = 0;
730 :
731 1 : return lua_load(L, ngx_http_lua_clfactory_getS, &ls, name);
732 : }
733 :
734 :
735 : static const char *
736 0 : ngx_http_lua_clfactory_getF(lua_State *L, void *ud, size_t *size)
737 : {
738 : char *buf;
739 : size_t num;
740 :
741 : ngx_http_lua_clfactory_file_ctx_t *lf;
742 :
743 0 : lf = (ngx_http_lua_clfactory_file_ctx_t *) ud;
744 :
745 0 : if (lf->extraline) {
746 0 : lf->extraline = 0;
747 0 : *size = 1;
748 0 : return "\n";
749 : }
750 :
751 0 : if (lf->sent_begin == 0) {
752 0 : lf->sent_begin = 1;
753 0 : *size = lf->begin_code_len;
754 :
755 0 : if (lf->file_type == NGX_LUA_TEXT_FILE) {
756 0 : buf = lf->begin_code.ptr;
757 :
758 : } else {
759 0 : buf = lf->begin_code.str;
760 : }
761 :
762 0 : return buf;
763 : }
764 :
765 0 : num = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
766 :
767 : dd("fread returned %d", (int) num);
768 :
769 0 : if (num == 0) {
770 0 : if (lf->sent_end == 0) {
771 0 : lf->sent_end = 1;
772 0 : *size = lf->end_code_len;
773 :
774 0 : if (lf->file_type == NGX_LUA_BT_LUA) {
775 0 : buf = lf->end_code.str;
776 :
777 : } else {
778 0 : buf = lf->end_code.ptr;
779 : }
780 :
781 0 : return buf;
782 : }
783 :
784 0 : *size = 0;
785 0 : return NULL;
786 : }
787 :
788 0 : if (lf->file_type == NGX_LUA_BT_LJ) {
789 : /* skip the footer(\x00) in luajit */
790 :
791 0 : lf->rest_len -= num;
792 :
793 0 : if (lf->rest_len == 0) {
794 0 : if (--num == 0 && lf->sent_end == 0) {
795 0 : lf->sent_end = 1;
796 0 : buf = lf->end_code.ptr;
797 0 : *size = lf->end_code_len;
798 :
799 0 : return buf;
800 : }
801 : }
802 : }
803 :
804 0 : *size = num;
805 0 : return lf->buff;
806 : }
807 :
808 :
809 : static int
810 0 : ngx_http_lua_clfactory_errfile(lua_State *L, const char *what, int fname_index)
811 : {
812 : const char *serr;
813 : const char *filename;
814 :
815 0 : filename = lua_tostring(L, fname_index) + 1;
816 :
817 0 : if (errno) {
818 0 : serr = strerror(errno);
819 0 : lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
820 :
821 : } else {
822 0 : lua_pushfstring(L, "cannot %s %s", what, filename);
823 : }
824 :
825 0 : lua_remove(L, fname_index);
826 :
827 0 : return LUA_ERRFILE;
828 : }
829 :
830 :
831 : static const char *
832 4 : ngx_http_lua_clfactory_getS(lua_State *L, void *ud, size_t *size)
833 : {
834 4 : ngx_http_lua_clfactory_buffer_ctx_t *ls = ud;
835 :
836 4 : if (ls->sent_begin == 0) {
837 1 : ls->sent_begin = 1;
838 1 : *size = CLFACTORY_BEGIN_SIZE;
839 :
840 1 : return CLFACTORY_BEGIN_CODE;
841 : }
842 :
843 3 : if (ls->size == 0) {
844 2 : if (ls->sent_end == 0) {
845 1 : ls->sent_end = 1;
846 1 : *size = CLFACTORY_END_SIZE;
847 1 : return CLFACTORY_END_CODE;
848 : }
849 :
850 1 : return NULL;
851 : }
852 :
853 1 : *size = ls->size;
854 1 : ls->size = 0;
855 :
856 1 : return ls->s;
857 : }
858 :
859 :
860 : static long
861 0 : ngx_http_lua_clfactory_file_size(FILE *f)
862 : {
863 : long cur_pos, len;
864 :
865 0 : cur_pos = ftell(f);
866 0 : if (cur_pos == -1) {
867 0 : return -1;
868 : }
869 :
870 0 : if (fseek(f, 0, SEEK_END) != 0) {
871 0 : return -1;
872 : }
873 :
874 0 : len = ftell(f);
875 0 : if (len == -1) {
876 0 : return -1;
877 : }
878 :
879 0 : if (fseek(f, cur_pos, SEEK_SET) != 0) {
880 0 : return -1;
881 : }
882 :
883 0 : return len;
884 : }
885 :
886 :
887 : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
|