immunio 1.1.13 → 1.1.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67b141794571c8c22164d0747303ae976b47ce0c
4
- data.tar.gz: 7fe8103a055bbceec95db059e986d43038bd33f9
3
+ metadata.gz: 7ae2946181dda203daf7cce9652ac99d78f0c822
4
+ data.tar.gz: c5c3ef8b2ab329ac11e5f3823601df36db381853
5
5
  SHA512:
6
- metadata.gz: 4f1b26c8e09aeff86edfd5040a73b696994a199f2e576a1a50c0a7fb9980183d7123070a5a9ff9111ac9c53b26fce27a58c56b967c51974386cbdafa8ec74698
7
- data.tar.gz: 0599ef0dfc60a801631dcda7c50358fbbfa69cac7e98f2b678582f88075632cd627871bca2df25646b9bef1098dd768ed535dab5ff2d8218bea07cb7720bdc7c
6
+ metadata.gz: ce62844b8ece04eaef147d59391ede1299b46734078ab3e5c1f4bf2965fa57544ed1a7439797a9cc1bda6dffe3473af2411f04d8a513ef199b8e3e2658761c54
7
+ data.tar.gz: 266a2912f823c888e4c61ed20c84b2a780592f60ad1f6b581d1bbe5587b386b99347d2bb70f21815ce357b65221c9895135751d2e72a9e11519e6575925df8fd
@@ -1,5 +1,6 @@
1
1
  # Hook into ActionView rendering to inject Immunio's hooks.
2
2
  require 'securerandom'
3
+ require 'ripper'
3
4
 
4
5
  module Immunio
5
6
  # Renders templates by filtering them through Immunio's hook handlers.
@@ -237,6 +238,18 @@ module Immunio
237
238
  end
238
239
  end
239
240
 
241
+ def self.remove_comment(code)
242
+ *, last_line = code.rpartition("\n")
243
+
244
+ comment = Ripper.slice(last_line, "comment")
245
+
246
+ if comment
247
+ code = code.sub(Regexp.new(Regexp.escape(comment) + "\\Z"), "")
248
+ end
249
+
250
+ code
251
+ end
252
+
240
253
  # Generate code injected in templates to wrap everything inside `<%= ... %>`.
241
254
  def self.generate_render_var_code(code, escape)
242
255
  template = Template.current
@@ -250,7 +263,7 @@ module Immunio
250
263
  handler.class.name
251
264
  end
252
265
 
253
- "(__immunio_result = (#{code}); Immunio::Template.render_var(#{code.strip.inspect}, __immunio_result, #{template_id}, '#{template.template_sha}', __FILE__, __LINE__, #{escape}, #{template.is_text?}, '#{handler_name}'))"
266
+ "(__immunio_result = (#{remove_comment(code)}); Immunio::Template.render_var(#{code.strip.inspect}, __immunio_result, #{template_id}, '#{template.template_sha}', __FILE__, __LINE__, #{escape}, #{template.is_text?}, '#{handler_name}'))"
254
267
  else
255
268
  code
256
269
  end
@@ -568,9 +581,14 @@ Immunio::Plugin.load(
568
581
 
569
582
  ActionView::TemplateRenderer.send :include, Immunio::TemplateRendererHooks
570
583
  ActionView::Template.send :include, Immunio::TemplateHooks
571
- ActionController::Caching::Fragments.send(
572
- :include,
573
- Immunio::FragmentCachingHooks)
584
+
585
+ if Rails::VERSION::MAJOR < 5
586
+ ActionController::Caching::Fragments.send(
587
+ :include,
588
+ Immunio::FragmentCachingHooks)
589
+ else
590
+ AbstractController::Caching.send(:include, Immunio::FragmentCachingHooks)
591
+ end
574
592
 
575
593
  plugin.loaded! Rails.version
576
594
  end
@@ -168,7 +168,12 @@ module Immunio
168
168
  visit o.wheres, modifier: :where
169
169
  visit o.groups, modifier: :group
170
170
  visit o.windows, context
171
- visit o.having, modifier: :having
171
+
172
+ if Rails::VERSION::MAJOR > 4
173
+ visit o.havings, modifier: :having
174
+ else
175
+ visit o.having, modifier: :having
176
+ end
172
177
  end
173
178
 
174
179
  def visit_Arel_Nodes_SelectStatement(o, context, _opts)
@@ -41,8 +41,8 @@ module Immunio
41
41
  # Sometimes ActiveRecord creates a new relation with a new condition and
42
42
  # merges it into an existing relation. I'm not sure why, and I'm not going
43
43
  # to ask. Just copy the context data from the other relation into this one.
44
- def merge_with_immunio(other)
45
- return merge_without_immunio(other) unless other && !other.is_a?(Array)
44
+ def merge_with_immunio(other, *args)
45
+ return merge_without_immunio(other, *args) unless other && !other.is_a?(Array)
46
46
 
47
47
  # Rails 4 added the ability to call merge with a proc, like:
48
48
  #
@@ -51,7 +51,7 @@ module Immunio
51
51
  # We don't need to do anything here. If the proc calls relation methods,
52
52
  # they will be called on the right relation and everything will be good.
53
53
  if !other.is_a?(ActiveRecord::Relation) && other.respond_to?(:to_proc)
54
- return merge_without_immunio(other)
54
+ return merge_without_immunio(other, *args)
55
55
  end
56
56
 
57
57
  # Rails 4 added the ability to merge in a hash of conditions, like:
@@ -63,13 +63,13 @@ module Immunio
63
63
  if other.is_a?(Hash)
64
64
  # This shouldn't happen, but let's be safe.
65
65
  unless defined? ActiveRecord::Relation::HashMerger
66
- return merge_without_immunio(other)
66
+ return merge_without_immunio(other, *args)
67
67
  end
68
68
 
69
69
  other = ActiveRecord::Relation::HashMerger.new(self, other).other
70
70
  end
71
71
 
72
- spawned = merge_without_immunio(other)
72
+ spawned = merge_without_immunio(other, *args)
73
73
  Request.time "plugin", "Immunio::RelationTracking" do
74
74
  QueryTracker.instance.merge_relations spawned, other
75
75
  end
@@ -46,8 +46,14 @@ module Immunio
46
46
 
47
47
  # Unwrap the innermost original exception.
48
48
  def unwrap_exception(e)
49
- while e.respond_to?(:original_exception) && e.original_exception.is_a?(Exception)
50
- e = e.original_exception
49
+ if Rails::VERSION::MAJOR > 4
50
+ while e.respond_to?(:cause) && e.cause.is_a?(Exception)
51
+ e = e.cause
52
+ end
53
+ else
54
+ while e.respond_to?(:original_exception) && e.original_exception.is_a?(Exception)
55
+ e = e.original_exception
56
+ end
51
57
  end
52
58
  e
53
59
  end
@@ -1,5 +1,5 @@
1
1
  module Immunio
2
2
  AGENT_TYPE = "agent-ruby"
3
- VERSION = "1.1.13"
3
+ VERSION = "1.1.15"
4
4
  VM_VERSION = "2.2.0"
5
5
  end
data/lua-hooks/Makefile CHANGED
@@ -10,13 +10,18 @@ CXX_SRC :=
10
10
 
11
11
  SPECIAL_SRC :=
12
12
 
13
- LUA_SRC :=
13
+ LUA_BASE_SRC :=
14
+
15
+ LUA_PROTECT_SRC :=
14
16
 
15
17
  CLI_SRC := \
16
18
  ext/luajit/src/luajit.c
17
19
 
18
- # Include module definitions
19
- include $(patsubst %,%/module.mk,$(MODULES))
20
+ # Include lib module definitions if present
21
+ # It will be missing from the agent public distribution
22
+ -include lib/module.mk
23
+ # Include extension module definitions
24
+ include ext/module.mk
20
25
 
21
26
  OBJ := \
22
27
  $(patsubst %.c,%.o,$(filter %.c,$(SRC))) \
@@ -41,7 +46,8 @@ A_OUT = libimmunio.a
41
46
  include options.mk
42
47
 
43
48
  INIT_HOOK = hooks/__init__.lua
44
- HOOK_SRCS := $(wildcard hooks/*.lua) hooks/__init__.lua
49
+ INIT_NOPROTECT_HOOK = hooks/__init__noprotect.lua
50
+ HOOK_SRCS := $(wildcard hooks/*.lua) hooks/__init__.lua hooks/__init__noprotect.lua
45
51
  MIN_SRCS = $(HOOK_SRCS:hooks/%.lua=build/%.lua)
46
52
  HOOKS_TARBALL = hooks.tgz
47
53
  HOOKS_SRCS_TARBALL = hooks_srcs.tgz
@@ -50,7 +56,7 @@ LUAJIT_OUT = libluajit.a
50
56
  LUAJIT_OBJ = ext/luajit/src/${LUAJIT_OUT}
51
57
 
52
58
  # Build lua, run tests, and create hooks archive
53
- all: ${CLI} ${INIT_HOOK} ${HOOKS_TARBALL} ${HOOKS_SRCS_TARBALL}
59
+ all: ${CLI} ${INIT_HOOK} ${INIT_NOPROTECT_HOOK} ${HOOKS_TARBALL} ${HOOKS_SRCS_TARBALL}
54
60
 
55
61
  ${SO_OUT}: ${OBJ} ${SPECIAL_OBJ} ${LUAJIT_OBJ}
56
62
  ${CC} -shared ${CFLAGS} ${LIBS} -o $@ -lc $^
@@ -62,7 +68,11 @@ ${LUAJIT_OUT}: ${LUAJIT_OBJ}
62
68
  cp $^ $@
63
69
 
64
70
  ${LUAJIT_OBJ}:
65
- cd ext/luajit/src && MACOSX_DEPLOYMENT_TARGET="10.8" make CROSS="${CROSS}" CC=cc HOST_CC=cc XCFLAGS="${LUAJIT_XCFLAGS}" ${LUAJIT_OUT}
71
+ ifneq (,$(TARGET_SYS))
72
+ cd ext/luajit/src && make CROSS="${CROSS}" CC=cc HOST_CC=cc TARGET_SYS=$(TARGET_SYS) XCFLAGS="${LUAJIT_XCFLAGS}" ${LUAJIT_OUT}
73
+ else
74
+ cd ext/luajit/src && make XCFLAGS="${LUAJIT_XCFLAGS}" ${LUAJIT_OUT}
75
+ endif
66
76
 
67
77
  # Build lua executable for testing and compilation
68
78
  # Seperate compilation as we need the LUA_UNSAFE_MODE flag set...
@@ -71,10 +81,14 @@ ${CLI}: CXXFLAGS += ${UNSAFE_FLAG}
71
81
  ${CLI}: ${CLI_SRC} ${SRC} ${SPECIAL_OBJ} ${CXX_OBJ} ${LUAJIT_OBJ}
72
82
  ${CC} ${CFLAGS} ${LDFLAGS} -o $@ $^ ${LIBS}
73
83
 
74
- # Concatenate init hooks into one __init__.lua hook with two newlines in between
75
- ${INIT_HOOK}: ${LUA_SRC} ${CLI}
84
+ # Concatenate init hooks into one __init__.lua
85
+ ${INIT_NOPROTECT_HOOK}: ${LUA_BASE_SRC} ${CLI}
86
+ rm -f hooks/__init__noprotect.lua
87
+ ${CLI} ./luald.lua ${LUA_BASE_SRC} > hooks/__init__noprotect.lua
88
+
89
+ ${INIT_HOOK}: ${LUA_BASE_SRC} ${LUA_PROTECT_SRC} ${CLI}
76
90
  rm -f hooks/__init__.lua
77
- ${CLI} ./luald.lua ${LUA_SRC} > hooks/__init__.lua
91
+ ${CLI} ./luald.lua ${LUA_BASE_SRC} ${LUA_PROTECT_SRC} > hooks/__init__.lua
78
92
 
79
93
  build/%.lua: hooks/%.lua ${CLI}
80
94
  @mkdir -p build
@@ -100,6 +114,7 @@ ${CLI_OBJ} ${OBJ} ${CXX_OBJ} ${LUAJIT_OBJ}: CFLAGS += ${OPTIMIZE_FULL}
100
114
 
101
115
  cleanhooks:
102
116
  rm -f ${INIT_HOOK}
117
+ rm -f ${INIT_NOPROTECT_HOOK}
103
118
  rm -f build/*.lua
104
119
 
105
120
  clean: cleanhooks
@@ -109,9 +124,14 @@ clean: cleanhooks
109
124
  rm -rf build
110
125
  find . -name \*.o -delete
111
126
 
112
- test: ${CLI} ${INIT_HOOK} lint ${MIN_SRCS}
127
+ test: ${CLI} ${INIT_HOOK} ${INIT_NOPROTECT_HOOK} lint ${MIN_SRCS}
113
128
  @rm -f test_failed
114
129
  @for file in test/*_test.lua; do \
130
+ printf "\nRunning $$file\n"; \
131
+ TEST_NOPROTECT_HOOKS=1 TEST_BUILT_HOOKS=1 ${CLI} -e 'package.path="./LuaMinify/?.lua;" .. package.path' -l 'Strict' $$file || touch test_failed; \
132
+ TEST_BUILT_HOOKS=1 ${CLI} -e 'package.path="./LuaMinify/?.lua;" .. package.path' -l 'Strict' $$file || touch test_failed; \
133
+ done
134
+ @for file in test_protect/*_test.lua; do \
115
135
  printf "\nRunning $$file\n"; \
116
136
  TEST_BUILT_HOOKS=1 ${CLI} -e 'package.path="./LuaMinify/?.lua;" .. package.path' -l 'Strict' $$file || touch test_failed; \
117
137
  done
@@ -122,7 +142,7 @@ enable-console: cleanhooks
122
142
  cp lib/term.lua.dev lib/term.lua
123
143
  make
124
144
 
125
- lint: ${INIT_HOOK}
145
+ lint: ${INIT_HOOK} ${INIT_NOPROTECT_HOOK}
126
146
  @# Scan all lua files for lines with trailing spaces
127
147
  @# The leading `!` negates the logic, so this target fails if trailing
128
148
  @# spaces are found in any Lua file.
data/lua-hooks/ext/all.c CHANGED
@@ -48,8 +48,9 @@ static const luaL_Reg lj_lib_load[] = {
48
48
  { NULL, NULL }
49
49
  };
50
50
 
51
- // In unsafe mode define these as NOPs when we build a .so
52
- #if !defined(LUA_UNSAFE_MODE)
51
+ // Ruby agent requires these functions to be present.
52
+ // In safe mode, where they are not, we provide a noop.
53
+ #if !defined(LUA_UNSAFE_MODE) && !defined(LUA_NO_MOCK_UNSAFE)
53
54
  LUALIB_API int luaopen_io(lua_State *L) {
54
55
  return 0;
55
56
  }
@@ -66,4 +67,3 @@ LUALIB_API void luaL_openlibs(lua_State *L) {
66
67
  lua_call(L, 1, 0);
67
68
  }
68
69
  }
69
-
@@ -57,7 +57,7 @@ struct libinjection_sqli_token {
57
57
  */
58
58
  int count;
59
59
 
60
- char val[32];
60
+ char val[512];
61
61
  };
62
62
 
63
63
  typedef struct libinjection_sqli_token stoken_t;
@@ -96,6 +96,18 @@ int sqli_tokenize(lua_State *L) {
96
96
  lua_pushlstring(L, &state.tokenvec[0].type, 1);
97
97
  lua_setfield(L, -2, "type");
98
98
 
99
+ if (state.tokenvec[0].str_open != '\0') {
100
+ /* Token.str_open = str_open */
101
+ lua_pushlstring(L, &state.tokenvec[0].str_open, 1);
102
+ lua_setfield(L, -2, "str_open");
103
+ }
104
+
105
+ if (state.tokenvec[0].str_close != '\0') {
106
+ /* Token.str_close = str_open */
107
+ lua_pushlstring(L, &state.tokenvec[0].str_close, 1);
108
+ lua_setfield(L, -2, "str_close");
109
+ }
110
+
99
111
  /* Token.var_symbol_count = count for variable tokens */
100
112
  if (state.tokenvec[0].type == 'v') {
101
113
  lua_pushinteger(L, state.tokenvec[0].count);
@@ -107,6 +119,10 @@ int sqli_tokenize(lua_State *L) {
107
119
  state.tokenvec[0].len);
108
120
  lua_setfield(L, -2, "value");
109
121
 
122
+ /* Token.pos = pos */
123
+ lua_pushinteger(L, state.tokenvec[0].pos);
124
+ lua_setfield(L, -2, "pos");
125
+
110
126
  /* Tokens.append(Token) */
111
127
  lua_pushinteger(L, token_cnt++);
112
128
  lua_insert(L, -2); /* [..., token, index] --> [..., index, token] */
@@ -1,4 +1,10 @@
1
- HISTORY for LPeg 0.12
1
+ HISTORY for LPeg 1.0
2
+
3
+ * Changes from version 0.12 to 1.0
4
+ ---------------------------------
5
+ + group "names" can be any Lua value
6
+ + some bugs fixed
7
+ + other small improvements
2
8
 
3
9
  * Changes from version 0.11 to 0.12
4
10
  ---------------------------------
@@ -1,5 +1,5 @@
1
1
  /*
2
- ** $Id: lpcap.c,v 1.5 2014/12/12 16:58:47 roberto Exp $
2
+ ** $Id: lpcap.c,v 1.6 2015/06/15 16:09:57 roberto Exp $
3
3
  ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
4
4
  */
5
5
 
@@ -126,7 +126,7 @@ static Capture *findback (CapState *cs, Capture *cap) {
126
126
  continue; /* opening an enclosing capture: skip and get previous */
127
127
  if (captype(cap) == Cgroup) {
128
128
  getfromktable(cs, cap->idx); /* get group name */
129
- if (lua_equal(L, -2, -1)) { /* right group? */
129
+ if (lp_equal(L, -2, -1)) { /* right group? */
130
130
  lua_pop(L, 2); /* remove reference name and group name */
131
131
  return cap;
132
132
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- ** $Id: lpcap.h,v 1.1 2013/03/21 20:25:12 roberto Exp $
2
+ ** $Id: lpcap.h,v 1.3 2016/09/13 17:45:58 roberto Exp $
3
3
  */
4
4
 
5
5
  #if !defined(lpcap_h)
@@ -11,14 +11,27 @@
11
11
 
12
12
  /* kinds of captures */
13
13
  typedef enum CapKind {
14
- Cclose, Cposition, Cconst, Cbackref, Carg, Csimple, Ctable, Cfunction,
15
- Cquery, Cstring, Cnum, Csubst, Cfold, Cruntime, Cgroup
14
+ Cclose, /* not used in trees */
15
+ Cposition,
16
+ Cconst, /* ktable[key] is Lua constant */
17
+ Cbackref, /* ktable[key] is "name" of group to get capture */
18
+ Carg, /* 'key' is arg's number */
19
+ Csimple, /* next node is pattern */
20
+ Ctable, /* next node is pattern */
21
+ Cfunction, /* ktable[key] is function; next node is pattern */
22
+ Cquery, /* ktable[key] is table; next node is pattern */
23
+ Cstring, /* ktable[key] is string; next node is pattern */
24
+ Cnum, /* numbered capture; 'key' is number of value to return */
25
+ Csubst, /* substitution capture; next node is pattern */
26
+ Cfold, /* ktable[key] is function; next node is pattern */
27
+ Cruntime, /* not used in trees (is uses another type for tree) */
28
+ Cgroup /* ktable[key] is group's "name" */
16
29
  } CapKind;
17
30
 
18
31
 
19
32
  typedef struct Capture {
20
33
  const char *s; /* subject position */
21
- short idx; /* extra info about capture (group name, arg index, etc.) */
34
+ unsigned short idx; /* extra info (group name, arg index, etc.) */
22
35
  byte kind; /* kind of capture */
23
36
  byte siz; /* size of full capture + 1 (0 = not a full capture) */
24
37
  } Capture;
@@ -1,5 +1,5 @@
1
1
  /*
2
- ** $Id: lpcode.c,v 1.21 2014/12/12 17:01:29 roberto Exp $
2
+ ** $Id: lpcode.c,v 1.24 2016/09/15 17:46:13 roberto Exp $
3
3
  ** Copyright 2007, Lua.org & PUC-Rio (see 'lpeg.html' for license)
4
4
  */
5
5
 
@@ -13,7 +13,7 @@
13
13
  #include "lpcode.h"
14
14
 
15
15
 
16
- /* signals a "no-LpegInstruction */
16
+ /* signals a "no-instruction */
17
17
  #define NOINST -1
18
18
 
19
19
 
@@ -125,6 +125,27 @@ int tocharset (TTree *tree, Charset *cs) {
125
125
  }
126
126
 
127
127
 
128
+ /*
129
+ ** Visit a TCall node taking care to stop recursion. If node not yet
130
+ ** visited, return 'f(sib2(tree))', otherwise return 'def' (default
131
+ ** value)
132
+ */
133
+ static int callrecursive (TTree *tree, int f (TTree *t), int def) {
134
+ int key = tree->key;
135
+ assert(tree->tag == TCall);
136
+ assert(sib2(tree)->tag == TRule);
137
+ if (key == 0) /* node already visited? */
138
+ return def; /* return default value */
139
+ else { /* first visit */
140
+ int result;
141
+ tree->key = 0; /* mark call as already visited */
142
+ result = f(sib2(tree)); /* go to called rule */
143
+ tree->key = key; /* restore tree */
144
+ return result;
145
+ }
146
+ }
147
+
148
+
128
149
  /*
129
150
  ** Check whether a pattern tree has captures
130
151
  */
@@ -134,14 +155,17 @@ int hascaptures (TTree *tree) {
134
155
  case TCapture: case TRunTime:
135
156
  return 1;
136
157
  case TCall:
137
- tree = sib2(tree); goto tailcall; /* return hascaptures(sib2(tree)); */
158
+ return callrecursive(tree, hascaptures, 0);
159
+ case TRule: /* do not follow siblings */
160
+ tree = sib1(tree); goto tailcall;
138
161
  case TOpenCall: assert(0);
139
162
  default: {
140
163
  switch (numsiblings[tree->tag]) {
141
164
  case 1: /* return hascaptures(sib1(tree)); */
142
165
  tree = sib1(tree); goto tailcall;
143
166
  case 2:
144
- if (hascaptures(sib1(tree))) return 1;
167
+ if (hascaptures(sib1(tree)))
168
+ return 1;
145
169
  /* else return hascaptures(sib2(tree)); */
146
170
  tree = sib2(tree); goto tailcall;
147
171
  default: assert(numsiblings[tree->tag] == 0); return 0;
@@ -208,9 +232,9 @@ int checkaux (TTree *tree, int pred) {
208
232
 
209
233
  /*
210
234
  ** number of characters to match a pattern (or -1 if variable)
211
- ** ('count' avoids infinite loops for grammars)
212
235
  */
213
- int fixedlenx (TTree *tree, int count, int len) {
236
+ int fixedlen (TTree *tree) {
237
+ int len = 0; /* to accumulate in tail calls */
214
238
  tailcall:
215
239
  switch (tree->tag) {
216
240
  case TChar: case TSet: case TAny:
@@ -220,26 +244,29 @@ int fixedlenx (TTree *tree, int count, int len) {
220
244
  case TRep: case TRunTime: case TOpenCall:
221
245
  return -1;
222
246
  case TCapture: case TRule: case TGrammar:
223
- /* return fixedlenx(sib1(tree), count); */
247
+ /* return fixedlen(sib1(tree)); */
224
248
  tree = sib1(tree); goto tailcall;
225
- case TCall:
226
- if (count++ >= MAXRULES)
227
- return -1; /* may be a loop */
228
- /* else return fixedlenx(sib2(tree), count); */
229
- tree = sib2(tree); goto tailcall;
249
+ case TCall: {
250
+ int n1 = callrecursive(tree, fixedlen, -1);
251
+ if (n1 < 0)
252
+ return -1;
253
+ else
254
+ return len + n1;
255
+ }
230
256
  case TSeq: {
231
- len = fixedlenx(sib1(tree), count, len);
232
- if (len < 0) return -1;
233
- /* else return fixedlenx(sib2(tree), count, len); */
234
- tree = sib2(tree); goto tailcall;
257
+ int n1 = fixedlen(sib1(tree));
258
+ if (n1 < 0)
259
+ return -1;
260
+ /* else return fixedlen(sib2(tree)) + len; */
261
+ len += n1; tree = sib2(tree); goto tailcall;
235
262
  }
236
263
  case TChoice: {
237
- int n1, n2;
238
- n1 = fixedlenx(sib1(tree), count, len);
239
- if (n1 < 0) return -1;
240
- n2 = fixedlenx(sib2(tree), count, len);
241
- if (n1 == n2) return n1;
242
- else return -1;
264
+ int n1 = fixedlen(sib1(tree));
265
+ int n2 = fixedlen(sib2(tree));
266
+ if (n1 != n2 || n1 < 0)
267
+ return -1;
268
+ else
269
+ return len + n1;
243
270
  }
244
271
  default: assert(0); return 0;
245
272
  };
@@ -257,7 +284,7 @@ int fixedlenx (TTree *tree, int count, int len) {
257
284
  ** pattern (full set if nothing follows it).
258
285
  **
259
286
  ** The function returns 0 when this resulting set can be used for
260
- ** test LpegInstructions that avoid the pattern altogether.
287
+ ** test instructions that avoid the pattern altogether.
261
288
  ** A non-zero return can happen for two reasons:
262
289
  ** 1) match p '' -> '' ==> return has bit 1 set
263
290
  ** (tests cannot be used because they would always fail for an empty input);
@@ -332,7 +359,7 @@ static int getfirst (TTree *tree, const Charset *follow, Charset *firstset) {
332
359
  }
333
360
  /* else go through */
334
361
  }
335
- case TBehind: { /* LpegInstruction gives no new information */
362
+ case TBehind: { /* instruction gives no new information */
336
363
  /* call 'getfirst' only to check for math-time captures */
337
364
  int e = getfirst(sib1(tree), follow, firstset);
338
365
  loopset(i, firstset->cs[i] = follow->cs[i]); /* uses follow */
@@ -406,9 +433,9 @@ static int needfollow (TTree *tree) {
406
433
 
407
434
 
408
435
  /*
409
- ** size of an LpegInstruction
436
+ ** size of an instruction
410
437
  */
411
- int sizei (const LpegInstruction *i) {
438
+ int sizei (const Instruction *i) {
412
439
  switch((Opcode)i->i.code) {
413
440
  case ISet: case ISpan: return CHARSETINSTSIZE;
414
441
  case ITestSet: return CHARSETINSTSIZE + 1;
@@ -431,11 +458,11 @@ typedef struct CompileState {
431
458
 
432
459
 
433
460
  /*
434
- ** code generation is recursive; 'opt' indicates that the code is
435
- ** being generated under a 'IChoice' operator jumping to its end
436
- ** (that is, the match is "optional").
437
- ** 'tt' points to a previous test protecting this code. 'fl' is
438
- ** the follow set of the pattern.
461
+ ** code generation is recursive; 'opt' indicates that the code is being
462
+ ** generated as the last thing inside an optional pattern (so, if that
463
+ ** code is optional too, it can reuse the 'IChoice' already in place for
464
+ ** the outer pattern). 'tt' points to a previous test protecting this
465
+ ** code (or NOINST). 'fl' is the follow set of the pattern.
439
466
  */
440
467
  static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
441
468
  const Charset *fl);
@@ -444,16 +471,16 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
444
471
  void realloccode (lua_State *L, Pattern *p, int nsize) {
445
472
  void *ud;
446
473
  lua_Alloc f = lua_getallocf(L, &ud);
447
- void *newblock = f(ud, p->code, p->codesize * sizeof(LpegInstruction),
448
- nsize * sizeof(LpegInstruction));
474
+ void *newblock = f(ud, p->code, p->codesize * sizeof(Instruction),
475
+ nsize * sizeof(Instruction));
449
476
  if (newblock == NULL && nsize > 0)
450
477
  luaL_error(L, "not enough memory");
451
- p->code = (LpegInstruction *)newblock;
478
+ p->code = (Instruction *)newblock;
452
479
  p->codesize = nsize;
453
480
  }
454
481
 
455
482
 
456
- static int nextLpegInstruction (CompileState *compst) {
483
+ static int nextinstruction (CompileState *compst) {
457
484
  int size = compst->p->codesize;
458
485
  if (compst->ncode >= size)
459
486
  realloccode(compst->L, compst->p, size * 2);
@@ -464,8 +491,8 @@ static int nextLpegInstruction (CompileState *compst) {
464
491
  #define getinstr(cs,i) ((cs)->p->code[i])
465
492
 
466
493
 
467
- static int addLpegInstruction (CompileState *compst, Opcode op, int aux) {
468
- int i = nextLpegInstruction(compst);
494
+ static int addinstruction (CompileState *compst, Opcode op, int aux) {
495
+ int i = nextinstruction(compst);
469
496
  getinstr(compst, i).i.code = op;
470
497
  getinstr(compst, i).i.aux = aux;
471
498
  return i;
@@ -473,33 +500,33 @@ static int addLpegInstruction (CompileState *compst, Opcode op, int aux) {
473
500
 
474
501
 
475
502
  /*
476
- ** Add an LpegInstruction followed by space for an offset (to be set later)
503
+ ** Add an instruction followed by space for an offset (to be set later)
477
504
  */
478
505
  static int addoffsetinst (CompileState *compst, Opcode op) {
479
- int i = addLpegInstruction(compst, op, 0); /* LpegInstruction */
480
- addLpegInstruction(compst, (Opcode)0, 0); /* open space for offset */
506
+ int i = addinstruction(compst, op, 0); /* instruction */
507
+ addinstruction(compst, (Opcode)0, 0); /* open space for offset */
481
508
  assert(op == ITestSet || sizei(&getinstr(compst, i)) == 2);
482
509
  return i;
483
510
  }
484
511
 
485
512
 
486
513
  /*
487
- ** Set the offset of an LpegInstruction
514
+ ** Set the offset of an instruction
488
515
  */
489
- static void setoffset (CompileState *compst, int LpegInstruction, int offset) {
490
- getinstr(compst, LpegInstruction + 1).offset = offset;
516
+ static void setoffset (CompileState *compst, int instruction, int offset) {
517
+ getinstr(compst, instruction + 1).offset = offset;
491
518
  }
492
519
 
493
520
 
494
521
  /*
495
- ** Add a capture LpegInstruction:
496
- ** 'op' is the capture LpegInstruction; 'cap' the capture kind;
522
+ ** Add a capture instruction:
523
+ ** 'op' is the capture instruction; 'cap' the capture kind;
497
524
  ** 'key' the key into ktable; 'aux' is the optional capture offset
498
525
  **
499
526
  */
500
527
  static int addinstcap (CompileState *compst, Opcode op, int cap, int key,
501
528
  int aux) {
502
- int i = addLpegInstruction(compst, op, joinkindoff(cap, aux));
529
+ int i = addinstruction(compst, op, joinkindoff(cap, aux));
503
530
  getinstr(compst, i).i.key = key;
504
531
  return i;
505
532
  }
@@ -511,43 +538,43 @@ static int addinstcap (CompileState *compst, Opcode op, int cap, int key,
511
538
 
512
539
 
513
540
  /*
514
- ** Patch 'LpegInstruction' to jump to 'target'
541
+ ** Patch 'instruction' to jump to 'target'
515
542
  */
516
- static void jumptothere (CompileState *compst, int LpegInstruction, int target) {
517
- if (LpegInstruction >= 0)
518
- setoffset(compst, LpegInstruction, target - LpegInstruction);
543
+ static void jumptothere (CompileState *compst, int instruction, int target) {
544
+ if (instruction >= 0)
545
+ setoffset(compst, instruction, target - instruction);
519
546
  }
520
547
 
521
548
 
522
549
  /*
523
- ** Patch 'LpegInstruction' to jump to current position
550
+ ** Patch 'instruction' to jump to current position
524
551
  */
525
- static void jumptohere (CompileState *compst, int LpegInstruction) {
526
- jumptothere(compst, LpegInstruction, gethere(compst));
552
+ static void jumptohere (CompileState *compst, int instruction) {
553
+ jumptothere(compst, instruction, gethere(compst));
527
554
  }
528
555
 
529
556
 
530
557
  /*
531
- ** Code an IChar LpegInstruction, or IAny if there is an equivalent
558
+ ** Code an IChar instruction, or IAny if there is an equivalent
532
559
  ** test dominating it
533
560
  */
534
561
  static void codechar (CompileState *compst, int c, int tt) {
535
562
  if (tt >= 0 && getinstr(compst, tt).i.code == ITestChar &&
536
563
  getinstr(compst, tt).i.aux == c)
537
- addLpegInstruction(compst, IAny, 0);
564
+ addinstruction(compst, IAny, 0);
538
565
  else
539
- addLpegInstruction(compst, IChar, c);
566
+ addinstruction(compst, IChar, c);
540
567
  }
541
568
 
542
569
 
543
570
  /*
544
- ** Add a charset posfix to an LpegInstruction
571
+ ** Add a charset posfix to an instruction
545
572
  */
546
573
  static void addcharset (CompileState *compst, const byte *cs) {
547
574
  int p = gethere(compst);
548
575
  int i;
549
576
  for (i = 0; i < (int)CHARSETINSTSIZE - 1; i++)
550
- nextLpegInstruction(compst); /* space for buffer */
577
+ nextinstruction(compst); /* space for buffer */
551
578
  /* fill buffer with charset */
552
579
  loopset(j, getinstr(compst, p).buff[j] = cs[j]);
553
580
  }
@@ -556,7 +583,7 @@ static void addcharset (CompileState *compst, const byte *cs) {
556
583
  /*
557
584
  ** code a char set, optimizing unit sets for IChar, "complete"
558
585
  ** sets for IAny, and empty sets for IFail; also use an IAny
559
- ** when LpegInstruction is dominated by an equivalent test.
586
+ ** when instruction is dominated by an equivalent test.
560
587
  */
561
588
  static void codecharset (CompileState *compst, const byte *cs, int tt) {
562
589
  int c = 0; /* (=) to avoid warnings */
@@ -566,14 +593,14 @@ static void codecharset (CompileState *compst, const byte *cs, int tt) {
566
593
  case ISet: { /* non-trivial set? */
567
594
  if (tt >= 0 && getinstr(compst, tt).i.code == ITestSet &&
568
595
  cs_equal(cs, getinstr(compst, tt + 2).buff))
569
- addLpegInstruction(compst, IAny, 0);
596
+ addinstruction(compst, IAny, 0);
570
597
  else {
571
- addLpegInstruction(compst, ISet, 0);
598
+ addinstruction(compst, ISet, 0);
572
599
  addcharset(compst, cs);
573
600
  }
574
601
  break;
575
602
  }
576
- default: addLpegInstruction(compst, op, c); break;
603
+ default: addinstruction(compst, op, c); break;
577
604
  }
578
605
  }
579
606
 
@@ -582,7 +609,7 @@ static void codecharset (CompileState *compst, const byte *cs, int tt) {
582
609
  ** code a test set, optimizing unit sets for ITestChar, "complete"
583
610
  ** sets for ITestAny, and empty sets for IJmp (always fails).
584
611
  ** 'e' is true iff test should accept the empty string. (Test
585
- ** LpegInstructions in the current VM never accept the empty string.)
612
+ ** instructions in the current VM never accept the empty string.)
586
613
  */
587
614
  static int codetestset (CompileState *compst, Charset *cs, int e) {
588
615
  if (e) return NOINST; /* no test */
@@ -611,7 +638,7 @@ static int codetestset (CompileState *compst, Charset *cs, int e) {
611
638
  /*
612
639
  ** Find the final destination of a sequence of jumps
613
640
  */
614
- static int finaltarget (LpegInstruction *code, int i) {
641
+ static int finaltarget (Instruction *code, int i) {
615
642
  while (code[i].i.code == IJmp)
616
643
  i = target(code, i);
617
644
  return i;
@@ -621,7 +648,7 @@ static int finaltarget (LpegInstruction *code, int i) {
621
648
  /*
622
649
  ** final label (after traversing any jumps)
623
650
  */
624
- static int finallabel (LpegInstruction *code, int i) {
651
+ static int finallabel (Instruction *code, int i) {
625
652
  return finaltarget(code, target(code, i));
626
653
  }
627
654
 
@@ -631,20 +658,20 @@ static int finallabel (LpegInstruction *code, int i) {
631
658
  */
632
659
  static void codebehind (CompileState *compst, TTree *tree) {
633
660
  if (tree->u.n > 0)
634
- addLpegInstruction(compst, IBehind, tree->u.n);
661
+ addinstruction(compst, IBehind, tree->u.n);
635
662
  codegen(compst, sib1(tree), 0, NOINST, fullset);
636
663
  }
637
664
 
638
665
 
639
666
  /*
640
667
  ** Choice; optimizations:
641
- ** - when p1 is headfail
642
- ** - when first(p1) and first(p2) are disjoint; than
668
+ ** - when p1 is headfail or
669
+ ** when first(p1) and first(p2) are disjoint, than
643
670
  ** a character not in first(p1) cannot go to p1, and a character
644
671
  ** in first(p1) cannot go to p2 (at it is not in first(p2)).
645
672
  ** (The optimization is not valid if p1 accepts the empty string,
646
673
  ** as then there is no character at all...)
647
- ** - when p2 is empty and opt is true; a IPartialCommit can resuse
674
+ ** - when p2 is empty and opt is true; a IPartialCommit can reuse
648
675
  ** the Choice already active in the stack.
649
676
  */
650
677
  static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
@@ -671,7 +698,7 @@ static void codechoice (CompileState *compst, TTree *p1, TTree *p2, int opt,
671
698
  }
672
699
  else {
673
700
  /* <p1 / p2> ==
674
- test(fail(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */
701
+ test(first(p1)) -> L1; choice L1; <p1>; commit L2; L1: <p2>; L2: */
675
702
  int pcommit;
676
703
  int test = codetestset(compst, &cs1, e1);
677
704
  int pchoice = addoffsetinst(compst, IChoice);
@@ -695,7 +722,7 @@ static void codeand (CompileState *compst, TTree *tree, int tt) {
695
722
  if (n >= 0 && n <= MAXBEHIND && !hascaptures(tree)) {
696
723
  codegen(compst, tree, 0, tt, fullset);
697
724
  if (n > 0)
698
- addLpegInstruction(compst, IBehind, n);
725
+ addinstruction(compst, IBehind, n);
699
726
  }
700
727
  else { /* default: Choice L1; p1; BackCommit L2; L1: Fail; L2: */
701
728
  int pcommit;
@@ -703,16 +730,17 @@ static void codeand (CompileState *compst, TTree *tree, int tt) {
703
730
  codegen(compst, tree, 0, tt, fullset);
704
731
  pcommit = addoffsetinst(compst, IBackCommit);
705
732
  jumptohere(compst, pchoice);
706
- addLpegInstruction(compst, IFail, 0);
733
+ addinstruction(compst, IFail, 0);
707
734
  jumptohere(compst, pcommit);
708
735
  }
709
736
  }
710
737
 
711
738
 
712
739
  /*
713
- ** Captures: if pattern has fixed (and not too big) length, use
714
- ** a single IFullCapture LpegInstruction after the match; otherwise,
715
- ** enclose the pattern with OpenCapture - CloseCapture.
740
+ ** Captures: if pattern has fixed (and not too big) length, and it
741
+ ** has no nested captures, use a single IFullCapture instruction
742
+ ** after the match; otherwise, enclose the pattern with OpenCapture -
743
+ ** CloseCapture.
716
744
  */
717
745
  static void codecapture (CompileState *compst, TTree *tree, int tt,
718
746
  const Charset *fl) {
@@ -738,7 +766,7 @@ static void coderuntime (CompileState *compst, TTree *tree, int tt) {
738
766
 
739
767
  /*
740
768
  ** Repetion; optimizations:
741
- ** When pattern is a charset, can use special LpegInstruction ISpan.
769
+ ** When pattern is a charset, can use special instruction ISpan.
742
770
  ** When pattern is head fail, or if it starts with characters that
743
771
  ** are disjoint from what follows the repetions, a simple test
744
772
  ** is enough (a fail inside the repetition would backtrack to fail
@@ -750,7 +778,7 @@ static void coderep (CompileState *compst, TTree *tree, int opt,
750
778
  const Charset *fl) {
751
779
  Charset st;
752
780
  if (tocharset(tree, &st)) {
753
- addLpegInstruction(compst, ISpan, 0);
781
+ addinstruction(compst, ISpan, 0);
754
782
  addcharset(compst, st.cs);
755
783
  }
756
784
  else {
@@ -759,7 +787,7 @@ static void coderep (CompileState *compst, TTree *tree, int opt,
759
787
  /* L1: test (fail(p1)) -> L2; <p>; jmp L1; L2: */
760
788
  int jmp;
761
789
  int test = codetestset(compst, &st, 0);
762
- codegen(compst, tree, opt, test, fullset);
790
+ codegen(compst, tree, 0, test, fullset);
763
791
  jmp = addoffsetinst(compst, IJmp);
764
792
  jumptohere(compst, test);
765
793
  jumptothere(compst, jmp, test);
@@ -797,12 +825,12 @@ static void codenot (CompileState *compst, TTree *tree) {
797
825
  int e = getfirst(tree, fullset, &st);
798
826
  int test = codetestset(compst, &st, e);
799
827
  if (headfail(tree)) /* test (fail(p1)) -> L1; fail; L1: */
800
- addLpegInstruction(compst, IFail, 0);
828
+ addinstruction(compst, IFail, 0);
801
829
  else {
802
830
  /* test(fail(p))-> L1; choice L1; <p>; failtwice; L1: */
803
831
  int pchoice = addoffsetinst(compst, IChoice);
804
832
  codegen(compst, tree, 0, NOINST, fullset);
805
- addLpegInstruction(compst, IFailTwice, 0);
833
+ addinstruction(compst, IFailTwice, 0);
806
834
  jumptohere(compst, pchoice);
807
835
  }
808
836
  jumptohere(compst, test);
@@ -816,7 +844,7 @@ static void codenot (CompileState *compst, TTree *tree) {
816
844
  static void correctcalls (CompileState *compst, int *positions,
817
845
  int from, int to) {
818
846
  int i;
819
- LpegInstruction *code = compst->p->code;
847
+ Instruction *code = compst->p->code;
820
848
  for (i = from; i < to; i += sizei(&code[i])) {
821
849
  if (code[i].i.code == IOpenCall) {
822
850
  int n = code[i].i.key; /* rule number */
@@ -848,7 +876,7 @@ static void codegrammar (CompileState *compst, TTree *grammar) {
848
876
  for (rule = sib1(grammar); rule->tag == TRule; rule = sib2(rule)) {
849
877
  positions[rulenumber++] = gethere(compst); /* save rule position */
850
878
  codegen(compst, sib1(rule), 0, NOINST, fullset); /* code rule */
851
- addLpegInstruction(compst, IRet, 0);
879
+ addinstruction(compst, IRet, 0);
852
880
  }
853
881
  assert(rule->tag == TTrue);
854
882
  jumptohere(compst, jumptoend);
@@ -893,10 +921,10 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
893
921
  tailcall:
894
922
  switch (tree->tag) {
895
923
  case TChar: codechar(compst, tree->u.n, tt); break;
896
- case TAny: addLpegInstruction(compst, IAny, 0); break;
924
+ case TAny: addinstruction(compst, IAny, 0); break;
897
925
  case TSet: codecharset(compst, treebuffer(tree), tt); break;
898
926
  case TTrue: break;
899
- case TFalse: addLpegInstruction(compst, IFail, 0); break;
927
+ case TFalse: addinstruction(compst, IFail, 0); break;
900
928
  case TChoice: codechoice(compst, sib1(tree), sib2(tree), opt, fl); break;
901
929
  case TRep: coderep(compst, sib1(tree), opt, fl); break;
902
930
  case TBehind: codebehind(compst, tree); break;
@@ -917,23 +945,23 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt,
917
945
 
918
946
 
919
947
  /*
920
- ** Optimize jumps and other jump-like LpegInstructions.
921
- ** * Update labels of LpegInstructions with labels to their final
948
+ ** Optimize jumps and other jump-like instructions.
949
+ ** * Update labels of instructions with labels to their final
922
950
  ** destinations (e.g., choice L1; ... L1: jmp L2: becomes
923
951
  ** choice L2)
924
- ** * Jumps to other LpegInstructions that do jumps become those
925
- ** LpegInstructions (e.g., jump to return becomes a return; jump
952
+ ** * Jumps to other instructions that do jumps become those
953
+ ** instructions (e.g., jump to return becomes a return; jump
926
954
  ** to commit becomes a commit)
927
955
  */
928
956
  static void peephole (CompileState *compst) {
929
- LpegInstruction *code = compst->p->code;
957
+ Instruction *code = compst->p->code;
930
958
  int i;
931
959
  for (i = 0; i < compst->ncode; i += sizei(&code[i])) {
932
960
  redo:
933
961
  switch (code[i].i.code) {
934
962
  case IChoice: case ICall: case ICommit: case IPartialCommit:
935
963
  case IBackCommit: case ITestChar: case ITestSet:
936
- case ITestAny: { /* LpegInstructions with labels */
964
+ case ITestAny: { /* instructions with labels */
937
965
  jumptothere(compst, i, finallabel(code, i)); /* optimize label */
938
966
  break;
939
967
  }
@@ -941,15 +969,15 @@ static void peephole (CompileState *compst) {
941
969
  int ft = finaltarget(code, i);
942
970
  switch (code[ft].i.code) { /* jumping to what? */
943
971
  case IRet: case IFail: case IFailTwice:
944
- case IEnd: { /* LpegInstructions with unconditional implicit jumps */
945
- code[i] = code[ft]; /* jump becomes that LpegInstruction */
972
+ case IEnd: { /* instructions with unconditional implicit jumps */
973
+ code[i] = code[ft]; /* jump becomes that instruction */
946
974
  code[i + 1].i.code = IAny; /* 'no-op' for target position */
947
975
  break;
948
976
  }
949
977
  case ICommit: case IPartialCommit:
950
978
  case IBackCommit: { /* inst. with unconditional explicit jumps */
951
979
  int fft = finallabel(code, ft);
952
- code[i] = code[ft]; /* jump becomes that LpegInstruction... */
980
+ code[i] = code[ft]; /* jump becomes that instruction... */
953
981
  jumptothere(compst, i, fft); /* but must correct its offset */
954
982
  goto redo; /* reoptimize its label */
955
983
  }
@@ -970,12 +998,12 @@ static void peephole (CompileState *compst) {
970
998
  /*
971
999
  ** Compile a pattern
972
1000
  */
973
- LpegInstruction *compile (lua_State *L, Pattern *p) {
1001
+ Instruction *compile (lua_State *L, Pattern *p) {
974
1002
  CompileState compst;
975
1003
  compst.p = p; compst.ncode = 0; compst.L = L;
976
1004
  realloccode(L, p, 2); /* minimum initial size */
977
1005
  codegen(&compst, p->tree, 0, NOINST, fullset);
978
- addLpegInstruction(&compst, IEnd, 0);
1006
+ addinstruction(&compst, IEnd, 0);
979
1007
  realloccode(L, p, compst.ncode); /* set final size */
980
1008
  peephole(&compst);
981
1009
  return p->code;