LCOV - code coverage report
Current view: top level - home/build/openresty-1.13.6.1/build/ngx_lua-0.10.11/src - ngx_http_lua_clfactory.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 21 224 9.4 %
Date: 2020-03-03 04:25:50 Functions: 2 7 28.6 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.13