immunio 1.1.13 → 1.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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;