Thursday, 15 April 2010

javascript - Safely parsing and evaluating user input -



javascript - Safely parsing and evaluating user input -

i'm working on project that's templating domain-specific language. in project, take lines of user input in next form:

'{{index(1, 5)}}' '{{firstname()}} x. {{lastname()}}' '{{floating(-0.5, 0.5)}}' '{{text(5, "words")}}'

any command between double curly braces ({{ }}) has corresponding javascript method should called when command encountered. (for example, function index(min, max) {...} in case of first one).

i'm having hard time figuring out how safely take input , phone call appropriate function. know way i'm doing isn't safe. eval() between 2 sets of curly braces.

how can parse these input strings such can flexibly match function phone call between curly braces , execute function parameters given, while still not blindly calling eval() code?

i've considered making mapping (if command index(), phone call function index() {}), doesn't seem flexible; how collect , pass parameters (e.g. {{index(2, 5)}}) if present?

this written in node.js.

this problem breaks downwards into:

parsing string

evaluating resulting function graph

dispatching each function (as part of #2 above)

parsing string

unfortunately, requirements have, parsing {{...}} string quite complex. have @ to the lowest degree these issues deal with:

functions can nested {{function1(function2(), 2, 3)}}.

strings can contain (escaped) quotes, , can contain commas, without requirement #1 above trivial approach finding discrete arguments (splitting on comma) won't work.

so...you need proper parser. seek cobble 1 advertisement hoc, parser generators come picture, peg.js or jison (those examples, not recommendations — did happen notice 1 of jison examples json parser, half battle). writing parser out of scope answering question on i'm afraid. :-)

evaluating resulting function graph

depending on tool use, parser generator may handle you. (i'm pretty sure peg.js , jison both would, instance.)

if not, after parsing you'll presumably end object graph of sort, gives functions , arguments (which might functions arguments...which might be...).

functiona 1 "two" functionb "a" functionc 42 functiond 27

functiona there has 5 arguments, 3rd of functionb 2 arguments, , on.

your next task, then, evaluate functions deepest first (and @ same depth, left-to-right) , replace them in relevant arguments list result, you'll need depth-first traversal algorithm. deepest first , left-to-right (top-to-bottom in bullet list above) mean in list above, have phone call functionc first, functionb, functiond, , functiona.

dispatching each function

depending 1 time again on tool use, may handle bit too. 1 time again suspect peg.js does, , wouldn't surprised if jison did well.

at point you're ready phone call function (no longer) has function calls arguments, you'll presumably have function name , array of arguments. assuming store functions in map:

var functions = { index: function() { /* ... */ }, firstname: function() { /* ... */ }, // ... };

...calling them easy bit:

functionresult = functions[functionname].apply(undefined, functionarguments);

i'm sorry not able "just x, , you're there," isn't trivial problem. throw tools @ it, wouldn't invent wheel myself.

javascript node.js parsing eval

No comments:

Post a Comment