lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


>>>>> "Andrew" == Andrew Gierth <andrew@tao11.riddles.org.uk> writes:
>>>>> "Sean" == Sean Conner <sean@conman.org> writes:

 Sean> So I'm participating in this years National Novel Generation
 Sean> Month [1] and I finished my entry. While generating the output, I
 Sean> had to use Lua 5.1 because Lua 5.3 would crash---hard.

 Andrew> Looks like lpeg is at fault: substcap is passing a bad length to
 Andrew> luaL_addlstring.

 Andrew> Here in substcap:

 Andrew> 403         while (!isclosecap(cs->cap)) {  /* traverse nested captures */
 Andrew> 404           const char *next = cs->cap->s;
 Andrew> 405           luaL_addlstring(b, curr, next - curr);  /* add text up to capture */

 Andrew> "next" is 0x0 while "curr" is a valid pointer.

The offending null value of cs->cap->s comes from here:

/*
** Add capture values returned by a dynamic capture to the capture list
** 'base', nested inside a group capture. 'fd' indexes the first capture
** value, 'n' is the number of values (at least 1).
*/
static void adddyncaptures (const char *s, Capture *base, int n, int fd) {
  int i;
  base[0].kind = Cgroup;  /* create group capture */
  base[0].siz = 0;
  base[0].idx = 0;  /* make it an anonymous group */
  for (i = 1; i <= n; i++) {  /* add runtime captures */
...

This code thinks it can create an anonymous group capture with no valid
.s pointer (to contain the results of a match-time capture). I _think_
the failure is normally hidden by the fact that base[0] is _usually_ a
reuse of the same Capture that was used for the match-time capture
itself - except that the array of Capture structures might get
reallocated between the two uses, without preserving the old value of
the (now unused) Capture.

Here is a small testcase (note that shortening the string eliminates the
error):

local lpeg = require 'lpeg'
local P,Cs,Cmt = lpeg.P, lpeg.Cs, lpeg.Cmt
local pat1 = P"a" / "b" + Cmt(P"c", function(_,p) return p,"d" end) + P(1)
local pat = Cs(pat1^1)
print(pat:match("abcdabcdabcdabcdabcdabcdabcdabc"))'

-- 
Andrew.