TomFrost / Jexl

Javascript Expression Language: Powerful context-based expression parser and evaluator
MIT License
561 stars 92 forks source link

Character escaping with `\\` in a string #45

Open jarrodek opened 5 years ago

jarrodek commented 5 years ago

This issue was reported by one of my users: https://github.com/advanced-rest-client/arc-electron/issues/102

The user put the following text into the input:

{ 
  "regex1": "^([\\w][\\w\\s\\-]*[\\w]|[\\w])$", 
  "regex2": "^\\-?[1-9][0-9]*(\\.[0-9]+)?$", 
  "testParam3": "${placeholder}" 
}

The result of parsing it with Jexl is:

{ 
  "regex1": "^([\w][\\w\\s\\-]*[\\w]|[\\w])$", 
  "regex2": "^\-?[1-9][0-9]*(\\.[0-9]+)?$", 
  "testParam3": "someValueFromContext" 
}

The problem is with \\ characters in 1st and 2nd lines. They got truncated but only the first occurance. At first I thought it's my implementation but after tracing the execution it gets truncated when calling Jexl API.

Is there something I can do to prevent this behavior? Or can it be fixed in Jexl? Thanks

TomFrost commented 5 years ago

Hey @jarrodek -- sorry for the late response! I was mid-merge of the 2.0 branch and wanted to wrap that before starting new tickets.

I'm trying to wrap my head around this -- do you have code that reproduces the problem? It's unclear to me whether this is a multiline string that's being evaluated as a jexl expression, or whether this is being provided as the context and referenced from within a jexl expression.

Loceka commented 5 years ago

I also have some issues concerning the quote escaping with the 1.1.4 release.

Here is a PoC showing the problem :

var jexl = require('Jexl');

var jeval = function(e) {
    console.log(e);
    return jexl.eval(e);
}
jexl.addTransform("log", function(m) { console.log(m); });
jexl.addTransform("test", function(a, e) { return jeval(e); });

var instructions = "0|test('0|test(\\\'0|test(\\\\\'(\\\\\\\'message\\\\\\\')|log\\\\\')\\\')')";
jeval(instructions);

You can see I added a layer above jexl.eval (called jeval) but it can totally be removed, it is here only to log the expression and see what's wrong.

My code only fail if there are 3 (or more) imbrication levels. If there are less, the quotes are correctly escaped. Just test with var instructions = "0|test('0|test(\\\'\\\\\'message\\\\\'|log\\\')')"; to see it's fine.

Loceka commented 5 years ago

OK I found where my problem was from.

It is in the function _unquote (since I have a minified JS I can't tell much more) :

r.prototype._unquote = function(e) {
    var t = e[0],
        r = new RegExp("\\\\" + t, "g");
    return e.substr(1, e.length - 2).replace(r, t).replace(o, "\\"); // o = /\\\\/
}

The .replace(o, "\\") instruction messes up the quotes, I don't know what it was/is supposed to do. Maybe there is some side effect on removing it, but at least it does fix the unbalanced quotes.

So here is the corrected function :

r.prototype._unquote = function(e) {
    var t = e[0],
        r = new RegExp("\\\\" + t, "g");
    return e.substr(1, e.length - 2).replace(r, t);
}

From what I understood of the original post, it seems that it would solve it too.

jarrodek commented 5 years ago

Hi, Sorry for my late response. Busy here too ;) See the issue I referenced for the example (the second comment from the reporter).